Reading libraries and parameters
library(tidyverse)
library(quickpsy)
library(cowplot)
list.files("R", full.names = TRUE) %>% walk(source)
source("graphical_parameters.R")
source("parameters.R")
load(file = "logdata/dat_asym.RData")
Fixed lapse rate to 0% or 1%
fun_normal<- function(x, p) {
pnorm(x, p[1] - p[2], p[3]) - pnorm(x, p[1] + p[2], p[3])
}
fun_normal_asyn_one <- function(x, p) {
.01 + (1- .01) * pnorm(x, p[1] - p[2], p[3]) - (1- .01) * pnorm(x, p[1] + p[2], p[3])
}
fit_asym_without_asyn_zero <- quickpsy(dat_asym,
orientation, response,
fun = fun_normal,
parini = list(pini_origin_asym, pini_origin_asym, pini_scale),
grouping = .(subject, reference),
bootstrap = "none")
fit_asym_without_asyn_one <- quickpsy(dat_asym,
orientation, response,
fun = fun_normal_asyn_one,
parini = list(pini_origin_asym, pini_origin_asym, pini_scale),
grouping = .(subject, reference),
bootstrap = "none")
ms_asym_without_asyn_zero_vs_without_asyn_one <- model_selection_aic(
fit_asym_without_asyn_zero$aic, fit_asym_without_asyn_one$aic) %>%
mutate(best = if_else(best == "first",
"without_asyn_zero", "without_asyn_one"))
ms_asym_without_asyn_zero_vs_without_asyn_one %>%
group_by(best) %>%
count()
ggplot() + facet_grid(subject ~ reference) +
geom_point(data = fit_asym_without_asyn_zero$averages,
aes(x = orientation, y = prob)) +
geom_line(data = fit_asym_without_asyn_zero$curves,
aes(x = x, y = y, color = "without asyn zero")) +
geom_line(data = fit_asym_without_asyn_one$curves,
aes(x = x, y = y, color = "without asyn one")) +
geom_text(data = ms_asym_without_asyn_zero_vs_without_asyn_one,
aes(x = .7, y = .1, label = best), size = 3) +
theme_grey() + theme(legend.position = "top")

Adding a fixed lapse rate does not change much the fits.
Checking that the parameters do not reach the boundaries of the initial parameters
fit_asym_without_asyn_zero$par %>%
filter(parn == "p1") %>%
filter(abs(par) >= pini_origin_asym[2])
fit_asym_without_asyn_zero$par %>%
filter(parn == "p2") %>%
filter(abs(par) >= pini_origin_asym[2])
fit_asym_without_asyn_zero$par %>%
filter(parn == "p3") %>%
filter(abs(par) >= pini_scale[2])
One variable lapse rate vs fixed lapse rate
fun_normal_with_one_asyn <- function(x, p) {
p[4] + (1 - p[4]) * pnorm(x, p[1] - p[2], p[3]) - (1 - p[4]) * pnorm(x, p[1] + p[2], p[3])
}
fit_asym_with_one_asyn <- quickpsy(dat_asym,
orientation, response,
fun = fun_normal_with_one_asyn,
parini = list(pini_origin_asym, pini_origin_asym, pini_scale, pini_lapse),
grouping = .(subject, reference),
bootstrap = "none")
fit_asym_without_asyn_zero_better <- ms_asym_without_asyn_zero_vs_without_asyn_one %>%
filter(best == "without_asyn_zero") %>%
select(subject, reference)
fit_asym_without_asyn_one_better <- ms_asym_without_asyn_zero_vs_without_asyn_one %>%
filter(best == "without_asyn_one") %>%
select(subject, reference)
fit_asym_without_asyn_zero_better_logliks <- fit_asym_without_asyn_zero$logliks %>%
semi_join(fit_asym_without_asyn_zero_better, by = c("subject", "reference"))
fit_asym_without_asyn_one_better_logliks <- fit_asym_without_asyn_one$logliks %>%
semi_join(fit_asym_without_asyn_one_better, by = c("subject", "reference"))
fit_asym_without_asyn_logliks <- fit_asym_without_asyn_zero_better_logliks %>%
bind_rows(fit_asym_without_asyn_one_better_logliks)
ms_asym_with_one_asyn_vs_without_asyn <- model_selection_lrt(
fit_asym_with_one_asyn$logliks, fit_asym_without_asyn_logliks) %>%
mutate(best = if_else(best == "first",
"with_one_asyn", "without_asyn"))
fit_asym_with_one_asyn_better <- ms_asym_with_one_asyn_vs_without_asyn %>%
filter(best == "with_one_asyn") %>%
select(subject, reference)
fit_asym_without_asyn_zero_better_curves <- fit_asym_without_asyn_zero$curves %>%
semi_join(fit_asym_without_asyn_zero_better, by = c("subject", "reference"))
fit_asym_without_asyn_one_better_curves <- fit_asym_without_asyn_one$curves %>%
semi_join(fit_asym_without_asyn_one_better, by = c("subject", "reference"))
fit_asym_without_asyn_curves <- fit_asym_without_asyn_zero_better_curves %>%
bind_rows(fit_asym_without_asyn_one_better_curves)
ggplot() + facet_grid(subject ~ reference) +
geom_point(data = fit_asym_with_one_asyn$averages,
aes(x = orientation, y = prob)) +
geom_line(data = fit_asym_with_one_asyn$curves,
aes(x = x, y = y, color = "one asyn")) +
geom_line(data = fit_asym_without_asyn_curves,
aes(x = x, y = y, color = "without asyn")) +
geom_text(data = ms_asym_with_one_asyn_vs_without_asyn,
aes(x = .7, y = .1, label = best), size = 3) +
theme_grey() + theme(legend.position = "top")

Adding a lapse rate parameter produce poor fits.
Fitting
refs <- dat_asym %>% distinct(vertical, references, reference)
fit_asym_full_fun <- function(data) {
fun_1 <- function(x, p) pnorm(x, p[1] - p[2], p[3]) - pnorm(x, p[1] + p[2], p[3])
fun_2 <- function(x, p) pnorm(x, p[1] - p[4], p[6]) - pnorm(x, p[1] + p[5], p[6])
pini <- list(pini_origin_asym, pini_origin_asym, pini_scale,
pini_origin_asym, pini_origin_asym, pini_scale)
fun_df <- data %>%
distinct(references) %>%
arrange(references) %>%
bind_cols(tibble(fun = c(fun_1, fun_2)))
quickpsy(data, orientation, response, fun = fun_df, xmin = -4, xmax = 4,
parini = pini, bootstrap = "none", grouping = .(references),
threshold = FALSE)
}
fit_asym_full_same_slope_fun <- function(data) {
fun_1 <- function(x, p) pnorm(x, p[1] - p[2], p[3]) - pnorm(x, p[1] + p[2], p[3])
fun_2 <- function(x, p) pnorm(x, p[1] - p[4], p[3]) - pnorm(x, p[1] + p[5], p[3])
pini <- list(pini_origin_asym, pini_origin_asym, pini_scale,
pini_origin_asym, pini_origin_asym)
fun_df <- data %>%
distinct(references) %>%
arrange(references) %>%
bind_cols(tibble(fun = c(fun_1, fun_2)))
quickpsy(data, orientation, response, fun = fun_df, xmin = -4, xmax = 4,
parini = pini, bootstrap = "none", grouping = .(references),
threshold = FALSE)
}
fit_asym_full_sym_crit_fun <- function(data) {
fun_1 <- function(x, p) pnorm(x, p[1] - p[2], p[3]) - pnorm(x, p[1] + p[2], p[3])
fun_2 <- function(x, p) pnorm(x, p[1] - p[4], p[5]) - pnorm(x, p[1] + p[4], p[5])
pini <- list(pini_origin_asym, pini_origin_asym, pini_scale,
pini_origin_asym, pini_scale)
fun_df <- data %>%
distinct(references) %>%
arrange(references) %>%
bind_cols(tibble(fun = c(fun_1, fun_2)))
quickpsy(data, orientation, response, fun = fun_df, xmin = -4, xmax = 4,
parini = pini, bootstrap = "none", grouping = .(references),
threshold = FALSE)
}
fit_asym_full_sym_crit_same_fun <- function(data) {
fun_1 <- function(x, p) pnorm(x, p[1] - p[2], p[3]) - pnorm(x, p[1] + p[2], p[3])
fun_2 <- function(x, p) pnorm(x, p[1] - p[2], p[4]) - pnorm(x, p[1] + p[2], p[4])
pini <- list(pini_origin_asym, pini_origin_asym, pini_scale,
pini_scale)
fun_df <- data %>%
distinct(references) %>%
arrange(references) %>%
bind_cols(tibble(fun = c(fun_1, fun_2)))
quickpsy(data, orientation, response, fun = fun_df, xmin = -4, xmax = 4,
parini = pini, bootstrap = "none", grouping = .(references),
threshold = FALSE)
}
fit_asym_full_sym_crit_same_zero_fun <- function(data) {
fun_1 <- function(x, p) pnorm(x, - p[1], p[2]) - pnorm(x, p[1], p[2])
fun_2 <- function(x, p) pnorm(x, - p[1], p[3]) - pnorm(x, p[1], p[3])
pini <- list(pini_origin_asym, pini_scale, pini_scale)
fun_df <- data %>%
distinct(references) %>%
arrange(references) %>%
bind_cols(tibble(fun = c(fun_1, fun_2)))
quickpsy(data, orientation, response, fun = fun_df, xmin = -4, xmax = 4,
parini = pini, bootstrap = "none", grouping = .(references),
threshold = FALSE)
}
fit_asym_full_same_slope_sym_crit_fun <- function(data) {
fun_1 <- function(x, p) pnorm(x, p[1] - p[2], p[3]) - pnorm(x, p[1] + p[2], p[3])
fun_2 <- function(x, p) pnorm(x, p[1] - p[4], p[3]) - pnorm(x, p[1] + p[4], p[3])
pini <- list(pini_origin_asym, pini_origin_asym, pini_scale,
pini_origin_asym)
fun_df <- data %>%
distinct(references) %>%
arrange(references) %>%
bind_cols(tibble(fun = c(fun_1, fun_2)))
quickpsy(data, orientation, response, fun = fun_df, xmin = -4, xmax = 4,
parini = pini, bootstrap = "none", grouping = .(references),
threshold = FALSE)
}
fit_asym_full_same_slope_sym_crit_zero_fun <- function(data) {
fun_1 <- function(x, p) pnorm(x, - p[1], p[2]) - pnorm(x,p[1], p[2])
fun_2 <- function(x, p) pnorm(x, - p[3], p[2]) - pnorm(x, p[3], p[2])
pini <- list(pini_origin_asym, pini_scale,
pini_origin_asym)
fun_df <- data %>%
distinct(references) %>%
arrange(references) %>%
bind_cols(tibble(fun = c(fun_1, fun_2)))
quickpsy(data, orientation, response, fun = fun_df, xmin = -4, xmax = 4,
parini = pini, bootstrap = "none", grouping = .(references),
threshold = FALSE)
}
fit_asym_full_same_slope_sym_crit_same_fun <- function(data) {
fun_1 <- function(x, p) pnorm(x, p[1] - p[2], p[3]) - pnorm(x, p[1] + p[2], p[3])
fun_2 <- function(x, p) pnorm(x, p[1] - p[2], p[3]) - pnorm(x, p[1] + p[2], p[3])
pini <- list(pini_origin_asym, pini_origin_asym, pini_scale)
fun_df <- data %>%
distinct(references) %>%
arrange(references) %>%
bind_cols(tibble(fun = c(fun_1, fun_2)))
quickpsy(data, orientation, response, fun = fun_df, xmin = -4, xmax = 4,
parini = pini, bootstrap = "none", grouping = .(references),
threshold = FALSE)
}
fit_asym_full_same_slope_sym_crit_same_zero_fun <- function(data) {
fun_1 <- function(x, p) pnorm(x, - p[1], p[2]) - pnorm(x, p[1], p[2])
fun_2 <- function(x, p) pnorm(x, - p[1], p[2]) - pnorm(x, p[1], p[2])
pini <- list(pini_origin_asym, pini_scale)
fun_df <- data %>%
distinct(references) %>%
arrange(references) %>%
bind_cols(tibble(fun = c(fun_1, fun_2)))
quickpsy(data, orientation, response, fun = fun_df, xmin = -4, xmax = 4,
parini = pini, bootstrap = "none", grouping = .(references),
threshold = FALSE)
}
fit_asym_full_fun_zero <- function(data) {
fun_1 <- function(x, p) pnorm(x, - p[1], p[2]) - pnorm(x, p[1], p[2])
fun_2 <- function(x, p) pnorm(x, - p[3], p[4]) - pnorm(x, p[3], p[4])
pini <- list(pini_origin_asym, pini_scale,
pini_origin_asym, pini_scale)
fun_df <- data %>%
distinct(references) %>%
arrange(references) %>%
bind_cols(tibble(fun = c(fun_1, fun_2)))
quickpsy(data, orientation, response, fun = fun_df, xmin = -4, xmax = 4,
parini = pini, bootstrap = "none", grouping = .(references),
threshold = FALSE)
}
fit_asym_best <- dat_asym %>%
group_by(subject, vertical) %>%
nest() %>%
mutate(fit_asym_full = map(data, fit_asym_full_fun),
fit_asym_full_sym_crit = map(data, fit_asym_full_sym_crit_fun),
fit_asym_full_sym_crit_same = map(data, fit_asym_full_sym_crit_same_fun),
fit_asym_full_sym_crit_same_zero = map(data, fit_asym_full_sym_crit_same_zero_fun),
fit_asym_full_zero = map(data, fit_asym_full_fun_zero),
fit_asym_full_same_slope = map(data, fit_asym_full_same_slope_fun),
fit_asym_full_same_slope_sym_crit = map(data, fit_asym_full_same_slope_sym_crit_fun),
fit_asym_full_same_slope_sym_crit_zero = map(data, fit_asym_full_same_slope_sym_crit_zero_fun),
fit_asym_full_same_slope_sym_crit_same = map(data, fit_asym_full_same_slope_sym_crit_same_fun),
fit_asym_full_same_slope_sym_crit_same_zero = map(data, fit_asym_full_same_slope_sym_crit_same_zero_fun)) %>%
# fit_asym_zero = map(data, fit_asym_zero_fun),
# fit_asym_p = map(data, fit_asym_p_fun),
# fit_asym_d = map(data, fit_asym_d_fun)) %>%
select(-data)
Full
ggplot() + facet_wrap(subject ~ vertical, ncol = 6) +
geom_point(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full, "averages")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = orientation, y = prob, color = references)) +
geom_line(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full, "curves")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = x, y = y, color = references)) +
theme_grey() + theme(legend.position = "top")

Full same slope
ggplot() + facet_wrap(subject ~ vertical, ncol = 6) +
geom_point(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_same_slope, "averages")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = orientation, y = prob, color = references)) +
geom_line(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_same_slope, "curves")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = x, y = y, color = references)) +
theme_grey() + theme(legend.position = "top")

Full vs full same slope
asym_full_vs_full_same_slope <- fit_asym_best %>%
group_by(subject, vertical) %>%
transmute(fit_asym_full_loglik = map(fit_asym_full, "logliks"),
fit_asym_full_same_slope_loglik = map(fit_asym_full_same_slope, "logliks"),
best = map2_chr(fit_asym_full_loglik, fit_asym_full_same_slope_loglik,
~model_selection_lrt(.x, .y)$best))
asym_full_vs_full_same_slope %>%
group_by(best) %>%
count()
best_asym_full_no_same_slope <- asym_full_vs_full_same_slope %>%
filter(best == "first") %>%
select(subject, vertical)
best_asym_full_same_slope <- asym_full_vs_full_same_slope %>%
filter(best == "second") %>%
select(subject, vertical)
Full no same slope sym crit
ggplot() + facet_wrap(subject ~ vertical, ncol = 6) +
geom_point(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_sym_crit, "averages")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = orientation, y = prob, color = references)) +
geom_line(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_sym_crit, "curves")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = x, y = y, color = references)) +
theme_grey() + theme(legend.position = "top")

Full no same slope vs full no same slope sym crit
asym_full_no_same_slope_vs_full_no_same_slope_sym_crit <- fit_asym_best %>%
group_by(subject, vertical) %>%
transmute(fit_asym_full_loglik = map(fit_asym_full, "logliks"),
fit_asym_full_sym_crit_loglik = map(fit_asym_full_sym_crit, "logliks"),
best = map2_chr(fit_asym_full_loglik, fit_asym_full_sym_crit_loglik,
~model_selection_lrt(.x, .y)$best))
asym_full_no_same_slope_vs_full_no_same_slope_sym_crit %>%
semi_join(best_asym_full_no_same_slope) %>%
group_by(best) %>%
count()
Joining, by = c("subject", "vertical")
best_asym_full_no_same_slope_sym_crit <- asym_full_no_same_slope_vs_full_no_same_slope_sym_crit %>%
semi_join(best_asym_full_no_same_slope) %>%
filter(best == "second") %>%
select(subject, vertical)
Joining, by = c("subject", "vertical")
Full no same slope sym crit same
ggplot() + facet_wrap(subject ~ vertical, ncol = 6) +
geom_point(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_sym_crit_same, "averages")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = orientation, y = prob, color = references)) +
geom_line(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_sym_crit_same, "curves")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = x, y = y, color = references)) +
theme_grey() + theme(legend.position = "top")

Full no same slope sym crit vs full no same slope sym crit same
asym_full_no_same_slope_sym_crit_vs_full_no_same_slope_sym_crit_same <- fit_asym_best %>%
group_by(subject, vertical) %>%
transmute(fit_asym_full_sym_crit_loglik = map(fit_asym_full_sym_crit, "logliks"),
fit_asym_full_sym_crit_same_loglik = map(fit_asym_full_sym_crit_same, "logliks"),
best = map2_chr(fit_asym_full_sym_crit_loglik, fit_asym_full_sym_crit_same_loglik,
~model_selection_lrt(.x, .y)$best))
asym_full_no_same_slope_sym_crit_vs_full_no_same_slope_sym_crit_same %>%
semi_join(best_asym_full_no_same_slope_sym_crit) %>%
group_by(best) %>%
count()
Joining, by = c("subject", "vertical")
best_asym_full_no_same_slope_sym_crit_same <- asym_full_no_same_slope_sym_crit_vs_full_no_same_slope_sym_crit_same %>%
semi_join(best_asym_full_no_same_slope_sym_crit) %>%
filter(best == "second") %>%
select(subject, vertical)
Joining, by = c("subject", "vertical")
Full no same slope sym crit same zero
ggplot() + facet_wrap(subject ~ vertical, ncol = 6) +
geom_point(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_sym_crit_same_zero, "averages")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = orientation, y = prob, color = references)) +
geom_line(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_sym_crit_same_zero, "curves")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = x, y = y, color = references)) +
theme_grey() + theme(legend.position = "top")

Full no same slope sym crit same vs full no same slope sym crit same zero
asym_full_no_same_slope_sym_crit_same_vs_full_no_same_slope_sym_crit_same_zero <- fit_asym_best %>%
group_by(subject, vertical) %>%
transmute(fit_asym_full_sym_crit_same_loglik = map(fit_asym_full_sym_crit_same, "logliks"),
fit_asym_full_sym_crit_same_zero_loglik = map(fit_asym_full_sym_crit_same_zero, "logliks"),
best = map2_chr(fit_asym_full_sym_crit_same_loglik, fit_asym_full_sym_crit_same_zero_loglik,
~model_selection_lrt(.x, .y)$best))
asym_full_no_same_slope_sym_crit_same_vs_full_no_same_slope_sym_crit_same_zero %>%
semi_join(best_asym_full_no_same_slope_sym_crit_same) %>%
group_by(best) %>%
count()
Joining, by = c("subject", "vertical")
### Add to s vs d
best_asym_full_no_same_slope_sym_crit_same_no_zero <- asym_full_no_same_slope_sym_crit_same_vs_full_no_same_slope_sym_crit_same_zero %>%
semi_join(best_asym_full_no_same_slope_sym_crit_same) %>%
filter(best == "first") %>%
select(subject, vertical) %>%
mutate(best = "response")
Joining, by = c("subject", "vertical")
Full same slope sym crit
ggplot() + facet_wrap(subject ~ vertical, ncol = 6) +
geom_point(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_same_slope_sym_crit, "averages")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = orientation, y = prob, color = references)) +
geom_line(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_same_slope_sym_crit, "curves")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = x, y = y, color = references)) +
theme_grey() + theme(legend.position = "top")

Full same slope vs full same slope sym crit
asym_full_same_slope_vs_full_same_slope_sym_crit <- fit_asym_best %>%
group_by(subject, vertical) %>%
transmute(fit_asym_full_same_slope_loglik = map(fit_asym_full_same_slope, "logliks"),
fit_asym_full_same_slope_sym_crit_loglik = map(fit_asym_full_same_slope_sym_crit, "logliks"),
best = map2_chr(fit_asym_full_same_slope_loglik, fit_asym_full_same_slope_sym_crit_loglik,
~model_selection_lrt(.x, .y)$best))
asym_full_same_slope_vs_full_same_slope_sym_crit %>%
semi_join(best_asym_full_same_slope) %>%
group_by(best) %>%
count()
Joining, by = c("subject", "vertical")
### Add to s vs d
best_asym_full_same_slope_no_sym_crit <- asym_full_same_slope_vs_full_same_slope_sym_crit %>%
semi_join(best_asym_full_same_slope) %>%
filter(best == "first") %>%
select(subject, vertical) %>%
mutate(best = "no sym crit")
Joining, by = c("subject", "vertical")
best_asym_full_same_slope_sym_crit <- asym_full_same_slope_vs_full_same_slope_sym_crit %>%
semi_join(best_asym_full_same_slope) %>%
filter(best == "second") %>%
select(subject, vertical)
Joining, by = c("subject", "vertical")
Full same slope sym crit same
ggplot() + facet_wrap(subject ~ vertical, ncol = 6) +
geom_point(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_same_slope_sym_crit_same, "averages")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = orientation, y = prob, color = references)) +
geom_line(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_same_slope_sym_crit_same, "curves")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = x, y = y, color = references)) +
theme_grey() + theme(legend.position = "top")

Full same slope sym crit vs full same slope sym crit same
asym_full_same_slope_sym_crit_vs_full_same_slope_sym_crit_same <- fit_asym_best %>%
group_by(subject, vertical) %>%
transmute(fit_asym_full_same_slope_sym_crit_loglik = map(fit_asym_full_same_slope_sym_crit, "logliks"),
fit_asym_full_same_slope_sym_crit_same_loglik = map(fit_asym_full_same_slope_sym_crit_same, "logliks"),
best = map2_chr(fit_asym_full_same_slope_sym_crit_loglik, fit_asym_full_same_slope_sym_crit_same_loglik,
~model_selection_lrt(.x, .y)$best))
asym_full_same_slope_sym_crit_vs_full_same_slope_sym_crit_same %>%
semi_join(best_asym_full_same_slope_sym_crit) %>%
group_by(best) %>%
count()
Joining, by = c("subject", "vertical")
best_asym_full_same_slope_sym_crit_no_same <- asym_full_same_slope_sym_crit_vs_full_same_slope_sym_crit_same %>%
semi_join(best_asym_full_same_slope_sym_crit) %>%
filter(best == "first") %>%
select(subject, vertical)
Joining, by = c("subject", "vertical")
best_asym_full_same_slope_sym_crit_same <- asym_full_same_slope_sym_crit_vs_full_same_slope_sym_crit_same %>%
semi_join(best_asym_full_same_slope_sym_crit) %>%
filter(best == "second") %>%
select(subject, vertical)
Joining, by = c("subject", "vertical")
Full same slope sym crit no same zero
ggplot() + facet_wrap(subject ~ vertical, ncol = 6) +
geom_point(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_same_slope_sym_crit_zero, "averages")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = orientation, y = prob, color = references)) +
geom_line(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_same_slope_sym_crit_zero, "curves")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = x, y = y, color = references)) +
theme_grey() + theme(legend.position = "top")

Full same slope sym crit no same vs full same slope sym crit no same zero
asym_full_same_slope_sym_crit_no_same_vs_full_same_slope_sym_crit_no_same_zero <- fit_asym_best %>%
group_by(subject, vertical) %>%
transmute(fit_asym_full_same_slope_sym_crit_loglik = map(fit_asym_full_same_slope_sym_crit, "logliks"),
fit_asym_full_same_slope_sym_crit_zero_loglik = map(fit_asym_full_same_slope_sym_crit_zero, "logliks"),
best = map2_chr(fit_asym_full_same_slope_sym_crit_loglik, fit_asym_full_same_slope_sym_crit_zero_loglik,
~model_selection_lrt(.x, .y)$best))
asym_full_same_slope_sym_crit_no_same_vs_full_same_slope_sym_crit_no_same_zero %>%
semi_join(best_asym_full_same_slope_sym_crit_no_same) %>%
group_by(best) %>%
count()
Joining, by = c("subject", "vertical")
### Add to s vs d
best_asym_full_same_slope_sym_crit_no_same_no_zero <- asym_full_same_slope_sym_crit_no_same_vs_full_same_slope_sym_crit_no_same_zero %>%
semi_join(best_asym_full_same_slope_sym_crit_no_same) %>%
filter(best == "first") %>%
select(subject, vertical) %>%
mutate(best = "response")
Joining, by = c("subject", "vertical")
Full same slope sym crit same zero
ggplot() + facet_wrap(subject ~ vertical, ncol = 6) +
geom_point(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_same_slope_sym_crit_same_zero, "averages")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = orientation, y = prob, color = references)) +
geom_line(data = fit_asym_best %>%
mutate(temp = map(fit_asym_full_same_slope_sym_crit_same_zero, "curves")) %>%
select(subject, vertical, temp) %>%
unnest(temp),
aes(x = x, y = y, color = references)) +
theme_grey() + theme(legend.position = "top")

Full same slope sym crit same vs full same slope sym crit same zero
asym_full_same_slope_sym_crit_same_vs_full_same_slope_sym_crit_same_zero <- fit_asym_best %>%
group_by(subject, vertical) %>%
transmute(fit_asym_full_same_slope_sym_crit_same_loglik = map(fit_asym_full_same_slope_sym_crit_same, "logliks"),
fit_asym_full_same_slope_sym_crit_same_zero_loglik = map(fit_asym_full_same_slope_sym_crit_same_zero, "logliks"),
best = map2_chr(fit_asym_full_same_slope_sym_crit_same_loglik, fit_asym_full_same_slope_sym_crit_same_zero_loglik,
~model_selection_lrt(.x, .y)$best))
asym_full_same_slope_sym_crit_same_vs_full_same_slope_sym_crit_same_zero %>%
semi_join(best_asym_full_same_slope_sym_crit_same) %>%
group_by(best) %>%
count()
Joining, by = c("subject", "vertical")
### Add to s vs d
best_asym_full_same_slope_sym_crit_same_no_zero <- asym_full_same_slope_sym_crit_same_vs_full_same_slope_sym_crit_same_zero %>%
semi_join(best_asym_full_same_slope_sym_crit_same) %>%
filter(best == "first") %>%
select(subject, vertical) %>%
mutate(best = "sensory")
Joining, by = c("subject", "vertical")
### Add to s vs d
best_asym_full_same_slope_sym_crit_same_zero <- asym_full_same_slope_sym_crit_same_vs_full_same_slope_sym_crit_same_zero %>%
semi_join(best_asym_full_same_slope_sym_crit_same) %>%
filter(best == "second") %>%
select(subject, vertical) %>%
mutate(best = "zero")
Joining, by = c("subject", "vertical")
Averages, curves and parameters

Add all best
best_asym <- best_asym_full_no_same_slope_sym_crit_same_no_zero %>%
bind_rows(best_asym_full_same_slope_no_sym_crit) %>%
bind_rows(best_asym_full_same_slope_sym_crit_no_same_no_zero) %>%
bind_rows(best_asym_full_same_slope_sym_crit_same_no_zero) %>%
bind_rows(best_asym_full_same_slope_sym_crit_same_zero)
refs <- dat_asym %>% distinct(vertical, references, reference)
asym_averages_s_vs_d_best <- asym_averages_s_vs_d %>%
left_join(best_asym) %>%
left_join(refs)
Joining, by = c("subject", "vertical")
Joining, by = c("vertical", "references")
asym_curves_s_vs_d_best <- asym_curves_s_vs_d %>%
left_join(best_asym) %>%
left_join(refs)
Joining, by = c("subject", "vertical")
Joining, by = c("vertical", "references")
asym_par_s_vs_d_best <- asym_par_s_vs_d %>%
left_join(best_asym)
Joining, by = c("subject", "vertical")
asym_par_s_vs_d_best_long <- asym_par_s_vs_d_long %>%
left_join(best_asym)
Joining, by = c("subject", "vertical")
asym_par_s_vs_d_best_abs <- asym_par_s_vs_d_best_long %>%
select(subject, vertical, psensory, pdecisional, best) %>%
gather(parn, par, - subject, - vertical, -best) %>%
mutate(parn = if_else(parn == "psensory",
"Sensory\nbias", "Decisional\nbias"),
abs_par = abs(par))
Save data
save(asym_averages_s_vs_d_best, file = "logdata/asym_averages_s_vs_d_best.RData")
save(asym_curves_s_vs_d_best, file = "logdata/asym_curves_s_vs_d_best.RData")
save(asym_par_s_vs_d_best, file = "logdata/asym_par_s_vs_d_best.RData")
save(asym_par_s_vs_d_best_long, file = "logdata/asym_par_s_vs_d_best_long.RData")
save(asym_par_s_vs_d_best_abs, file = "logdata/asym_par_s_vs_d_best_abs.RData")
LS0tCnRpdGxlOiAiU3ltbWV0cmljIHRhc2sgIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIyMgUmVhZGluZyBsaWJyYXJpZXMgYW5kIHBhcmFtZXRlcnMKCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShxdWlja3BzeSkKbGlicmFyeShjb3dwbG90KQoKbGlzdC5maWxlcygiUiIsIGZ1bGwubmFtZXMgPSBUUlVFKSAlPiUgd2Fsayhzb3VyY2UpCnNvdXJjZSgiZ3JhcGhpY2FsX3BhcmFtZXRlcnMuUiIpCnNvdXJjZSgicGFyYW1ldGVycy5SIikKCmxvYWQoZmlsZSA9ICJsb2dkYXRhL2RhdF9hc3ltLlJEYXRhIikKYGBgCgoKIyMjIEZpeGVkIGxhcHNlIHJhdGUgdG8gMCUgb3IgMSUKCmBgYHtyIGZpZy5oZWlnaHQ9MjUsIGZpZy53aWR0aD04fQoKZnVuX25vcm1hbDwtIGZ1bmN0aW9uKHgsIHApIHsKICBwbm9ybSh4LCBwWzFdIC0gcFsyXSwgcFszXSkgLSBwbm9ybSh4LCBwWzFdICsgcFsyXSwgcFszXSkKfQoKZnVuX25vcm1hbF9hc3luX29uZSA8LSBmdW5jdGlvbih4LCBwKSB7CiAgLjAxICsgKDEtIC4wMSkgKiBwbm9ybSh4LCBwWzFdIC0gcFsyXSwgcFszXSkgLSAoMS0gLjAxKSAqIHBub3JtKHgsIHBbMV0gKyBwWzJdLCBwWzNdKQp9CgpmaXRfYXN5bV93aXRob3V0X2FzeW5femVybyA8LSBxdWlja3BzeShkYXRfYXN5bSwgCiAgICAgICAgICAgICAgICAgICAgIG9yaWVudGF0aW9uLCByZXNwb25zZSwgCiAgICAgICAgICAgICAgICAgICAgIGZ1biA9IGZ1bl9ub3JtYWwsCiAgICAgICAgICAgICAgICAgICAgIHBhcmluaSA9IGxpc3QocGluaV9vcmlnaW5fYXN5bSwgcGluaV9vcmlnaW5fYXN5bSwgcGluaV9zY2FsZSksCiAgICAgICAgICAgICAgICAgICAgIGdyb3VwaW5nID0gLihzdWJqZWN0LCByZWZlcmVuY2UpLAogICAgICAgICAgICAgICAgICAgICBib290c3RyYXAgPSAibm9uZSIpCgpmaXRfYXN5bV93aXRob3V0X2FzeW5fb25lIDwtIHF1aWNrcHN5KGRhdF9hc3ltLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmllbnRhdGlvbiwgcmVzcG9uc2UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1biA9IGZ1bl9ub3JtYWxfYXN5bl9vbmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyaW5pID0gbGlzdChwaW5pX29yaWdpbl9hc3ltLCBwaW5pX29yaWdpbl9hc3ltLCBwaW5pX3NjYWxlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cGluZyA9IC4oc3ViamVjdCwgcmVmZXJlbmNlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBib290c3RyYXAgPSAibm9uZSIpCgptc19hc3ltX3dpdGhvdXRfYXN5bl96ZXJvX3ZzX3dpdGhvdXRfYXN5bl9vbmUgPC0gbW9kZWxfc2VsZWN0aW9uX2FpYygKICBmaXRfYXN5bV93aXRob3V0X2FzeW5femVybyRhaWMsIGZpdF9hc3ltX3dpdGhvdXRfYXN5bl9vbmUkYWljKSAlPiUgCiAgbXV0YXRlKGJlc3QgPSBpZl9lbHNlKGJlc3QgPT0gImZpcnN0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICJ3aXRob3V0X2FzeW5femVybyIsICJ3aXRob3V0X2FzeW5fb25lIikpCgptc19hc3ltX3dpdGhvdXRfYXN5bl96ZXJvX3ZzX3dpdGhvdXRfYXN5bl9vbmUgJT4lIAogIGdyb3VwX2J5KGJlc3QpICU+JSAKICBjb3VudCgpIAoKZ2dwbG90KCkgKyBmYWNldF9ncmlkKHN1YmplY3QgfiByZWZlcmVuY2UpICsKICBnZW9tX3BvaW50KGRhdGEgPSBmaXRfYXN5bV93aXRob3V0X2FzeW5femVybyRhdmVyYWdlcywgCiAgICAgICAgICAgICBhZXMoeCA9IG9yaWVudGF0aW9uLCB5ID0gcHJvYikpICsKICBnZW9tX2xpbmUoZGF0YSA9IGZpdF9hc3ltX3dpdGhvdXRfYXN5bl96ZXJvJGN1cnZlcywgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gIndpdGhvdXQgYXN5biB6ZXJvIikpICsKICBnZW9tX2xpbmUoZGF0YSA9IGZpdF9hc3ltX3dpdGhvdXRfYXN5bl9vbmUkY3VydmVzLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSAid2l0aG91dCBhc3luIG9uZSIpKSArCiAgZ2VvbV90ZXh0KGRhdGEgPSBtc19hc3ltX3dpdGhvdXRfYXN5bl96ZXJvX3ZzX3dpdGhvdXRfYXN5bl9vbmUsCiAgICAgICAgICAgIGFlcyh4ID0gLjcsIHkgPSAuMSwgbGFiZWwgPSBiZXN0KSwgc2l6ZSA9IDMpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKCkFkZGluZyBhIGZpeGVkIGxhcHNlIHJhdGUgZG9lcyBub3QgY2hhbmdlIG11Y2ggdGhlIGZpdHMuIAoKCiMjIyBDaGVja2luZyB0aGF0IHRoZSBwYXJhbWV0ZXJzIGRvIG5vdCByZWFjaCB0aGUgYm91bmRhcmllcyBvZiB0aGUgaW5pdGlhbCBwYXJhbWV0ZXJzCgpgYGB7cn0KZml0X2FzeW1fd2l0aG91dF9hc3luX3plcm8kcGFyICU+JSAKICBmaWx0ZXIocGFybiA9PSAicDEiKSAlPiUgCiAgZmlsdGVyKGFicyhwYXIpID49IHBpbmlfb3JpZ2luX2FzeW1bMl0pCgpmaXRfYXN5bV93aXRob3V0X2FzeW5femVybyRwYXIgJT4lIAogIGZpbHRlcihwYXJuID09ICJwMiIpICU+JSAKICBmaWx0ZXIoYWJzKHBhcikgPj0gcGluaV9vcmlnaW5fYXN5bVsyXSkKCmZpdF9hc3ltX3dpdGhvdXRfYXN5bl96ZXJvJHBhciAlPiUgCiAgZmlsdGVyKHBhcm4gPT0gInAzIikgJT4lIAogIGZpbHRlcihhYnMocGFyKSA+PSBwaW5pX3NjYWxlWzJdKQpgYGAKCgojIyMgT25lIHZhcmlhYmxlIGxhcHNlIHJhdGUgdnMgZml4ZWQgbGFwc2UgcmF0ZQoKYGBge3IgZmlnLmhlaWdodD0yMCwgZmlnLndpZHRoPTh9CmZ1bl9ub3JtYWxfd2l0aF9vbmVfYXN5biA8LSBmdW5jdGlvbih4LCBwKSB7CiAgcFs0XSArICgxIC0gcFs0XSkgKiBwbm9ybSh4LCBwWzFdIC0gcFsyXSwgcFszXSkgLSAoMSAtIHBbNF0pICogcG5vcm0oeCwgcFsxXSArIHBbMl0sIHBbM10pCn0KCmZpdF9hc3ltX3dpdGhfb25lX2FzeW4gPC0gcXVpY2twc3koZGF0X2FzeW0sIAogICAgICAgICAgb3JpZW50YXRpb24sIHJlc3BvbnNlLCAKICAgICAgICAgIGZ1biA9IGZ1bl9ub3JtYWxfd2l0aF9vbmVfYXN5biwKICAgICAgICAgIHBhcmluaSA9IGxpc3QocGluaV9vcmlnaW5fYXN5bSwgcGluaV9vcmlnaW5fYXN5bSwgcGluaV9zY2FsZSwgcGluaV9sYXBzZSksCiAgICAgICAgICBncm91cGluZyA9IC4oc3ViamVjdCwgcmVmZXJlbmNlKSwKICAgICAgICAgIGJvb3RzdHJhcCA9ICJub25lIikKCgpmaXRfYXN5bV93aXRob3V0X2FzeW5femVyb19iZXR0ZXIgPC0gbXNfYXN5bV93aXRob3V0X2FzeW5femVyb192c193aXRob3V0X2FzeW5fb25lICU+JSAKICBmaWx0ZXIoYmVzdCA9PSAid2l0aG91dF9hc3luX3plcm8iKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIHJlZmVyZW5jZSkKCmZpdF9hc3ltX3dpdGhvdXRfYXN5bl9vbmVfYmV0dGVyIDwtIG1zX2FzeW1fd2l0aG91dF9hc3luX3plcm9fdnNfd2l0aG91dF9hc3luX29uZSAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gIndpdGhvdXRfYXN5bl9vbmUiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIHJlZmVyZW5jZSkKCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCmZpdF9hc3ltX3dpdGhvdXRfYXN5bl96ZXJvX2JldHRlcl9sb2dsaWtzIDwtIGZpdF9hc3ltX3dpdGhvdXRfYXN5bl96ZXJvJGxvZ2xpa3MgJT4lCiAgc2VtaV9qb2luKGZpdF9hc3ltX3dpdGhvdXRfYXN5bl96ZXJvX2JldHRlciwgYnkgPSBjKCJzdWJqZWN0IiwgInJlZmVyZW5jZSIpKQogIApmaXRfYXN5bV93aXRob3V0X2FzeW5fb25lX2JldHRlcl9sb2dsaWtzIDwtIGZpdF9hc3ltX3dpdGhvdXRfYXN5bl9vbmUkbG9nbGlrcyAlPiUKICBzZW1pX2pvaW4oZml0X2FzeW1fd2l0aG91dF9hc3luX29uZV9iZXR0ZXIsIGJ5ID0gYygic3ViamVjdCIsICJyZWZlcmVuY2UiKSkKCmZpdF9hc3ltX3dpdGhvdXRfYXN5bl9sb2dsaWtzIDwtIGZpdF9hc3ltX3dpdGhvdXRfYXN5bl96ZXJvX2JldHRlcl9sb2dsaWtzICU+JSAKICBiaW5kX3Jvd3MoZml0X2FzeW1fd2l0aG91dF9hc3luX29uZV9iZXR0ZXJfbG9nbGlrcykKICAKbXNfYXN5bV93aXRoX29uZV9hc3luX3ZzX3dpdGhvdXRfYXN5biA8LSBtb2RlbF9zZWxlY3Rpb25fbHJ0KAogIGZpdF9hc3ltX3dpdGhfb25lX2FzeW4kbG9nbGlrcywgZml0X2FzeW1fd2l0aG91dF9hc3luX2xvZ2xpa3MpICAlPiUgCiAgbXV0YXRlKGJlc3QgPSBpZl9lbHNlKGJlc3QgPT0gImZpcnN0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICJ3aXRoX29uZV9hc3luIiwgIndpdGhvdXRfYXN5biIpKQoKZml0X2FzeW1fd2l0aF9vbmVfYXN5bl9iZXR0ZXIgPC0gbXNfYXN5bV93aXRoX29uZV9hc3luX3ZzX3dpdGhvdXRfYXN5biAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gIndpdGhfb25lX2FzeW4iKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIHJlZmVyZW5jZSkKCmZpdF9hc3ltX3dpdGhvdXRfYXN5bl96ZXJvX2JldHRlcl9jdXJ2ZXMgPC0gZml0X2FzeW1fd2l0aG91dF9hc3luX3plcm8kY3VydmVzICU+JQogIHNlbWlfam9pbihmaXRfYXN5bV93aXRob3V0X2FzeW5femVyb19iZXR0ZXIsIGJ5ID0gYygic3ViamVjdCIsICJyZWZlcmVuY2UiKSkKICAKZml0X2FzeW1fd2l0aG91dF9hc3luX29uZV9iZXR0ZXJfY3VydmVzIDwtIGZpdF9hc3ltX3dpdGhvdXRfYXN5bl9vbmUkY3VydmVzICU+JQogIHNlbWlfam9pbihmaXRfYXN5bV93aXRob3V0X2FzeW5fb25lX2JldHRlciwgYnkgPSBjKCJzdWJqZWN0IiwgInJlZmVyZW5jZSIpKQoKZml0X2FzeW1fd2l0aG91dF9hc3luX2N1cnZlcyA8LSBmaXRfYXN5bV93aXRob3V0X2FzeW5femVyb19iZXR0ZXJfY3VydmVzICU+JSAKICBiaW5kX3Jvd3MoZml0X2FzeW1fd2l0aG91dF9hc3luX29uZV9iZXR0ZXJfY3VydmVzKQoKZ2dwbG90KCkgKyBmYWNldF9ncmlkKHN1YmplY3QgfiByZWZlcmVuY2UpICsKICBnZW9tX3BvaW50KGRhdGEgPSBmaXRfYXN5bV93aXRoX29uZV9hc3luJGF2ZXJhZ2VzLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iKSkgKwogIGdlb21fbGluZShkYXRhID0gZml0X2FzeW1fd2l0aF9vbmVfYXN5biRjdXJ2ZXMsIAogICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvciA9ICJvbmUgYXN5biIpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBmaXRfYXN5bV93aXRob3V0X2FzeW5fY3VydmVzLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSAid2l0aG91dCBhc3luIikpICsKICBnZW9tX3RleHQoZGF0YSA9IG1zX2FzeW1fd2l0aF9vbmVfYXN5bl92c193aXRob3V0X2FzeW4sIAogICAgICAgICAgICBhZXMoeCA9IC43LCB5ID0gLjEsIGxhYmVsID0gYmVzdCksIHNpemUgPSAzKSArCiAgdGhlbWVfZ3JleSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpIApgYGAKCkFkZGluZyBhIGxhcHNlIHJhdGUgcGFyYW1ldGVyIHByb2R1Y2UgcG9vciBmaXRzLiAKCgojIyMgRml0dGluZwpgYGB7ciBmaWcuaGVpZ2h0PTksIGZpZy53aWR0aD0xM30KcmVmcyA8LSBkYXRfYXN5bSAlPiUgZGlzdGluY3QodmVydGljYWwsIHJlZmVyZW5jZXMsIHJlZmVyZW5jZSkKCmZpdF9hc3ltX2Z1bGxfZnVuIDwtIGZ1bmN0aW9uKGRhdGEpIHsKICAKICBmdW5fMSA8LSBmdW5jdGlvbih4LCBwKSBwbm9ybSh4LCBwWzFdIC0gcFsyXSwgcFszXSkgLSBwbm9ybSh4LCBwWzFdICsgcFsyXSwgcFszXSkKICBmdW5fMiA8LSBmdW5jdGlvbih4LCBwKSBwbm9ybSh4LCBwWzFdIC0gcFs0XSwgcFs2XSkgLSBwbm9ybSh4LCBwWzFdICsgcFs1XSwgcFs2XSkKICAKICBwaW5pIDwtIGxpc3QocGluaV9vcmlnaW5fYXN5bSwgcGluaV9vcmlnaW5fYXN5bSwgcGluaV9zY2FsZSwgCiAgICAgICAgICAgICAgIHBpbmlfb3JpZ2luX2FzeW0sIHBpbmlfb3JpZ2luX2FzeW0sIHBpbmlfc2NhbGUpCgogIGZ1bl9kZiA8LSBkYXRhICU+JSAKICAgIGRpc3RpbmN0KHJlZmVyZW5jZXMpICU+JSAKICAgIGFycmFuZ2UocmVmZXJlbmNlcykgJT4lIAogICAgYmluZF9jb2xzKHRpYmJsZShmdW4gPSBjKGZ1bl8xLCBmdW5fMikpKSAKCiAgcXVpY2twc3koZGF0YSwgb3JpZW50YXRpb24sIHJlc3BvbnNlLCBmdW4gPSBmdW5fZGYsIHhtaW4gPSAtNCwgeG1heCA9IDQsCiAgICAgICAgICAgcGFyaW5pID0gcGluaSwgYm9vdHN0cmFwID0gIm5vbmUiLCBncm91cGluZyA9IC4ocmVmZXJlbmNlcyksCiAgICAgICAgICAgdGhyZXNob2xkID0gRkFMU0UpCn0KCmZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9mdW4gPC0gZnVuY3Rpb24oZGF0YSkgewogIAogIGZ1bl8xIDwtIGZ1bmN0aW9uKHgsIHApIHBub3JtKHgsIHBbMV0gLSBwWzJdLCBwWzNdKSAtIHBub3JtKHgsIHBbMV0gKyBwWzJdLCBwWzNdKQogIGZ1bl8yIDwtIGZ1bmN0aW9uKHgsIHApIHBub3JtKHgsIHBbMV0gLSBwWzRdLCBwWzNdKSAtIHBub3JtKHgsIHBbMV0gKyBwWzVdLCBwWzNdKQogIAogIHBpbmkgPC0gbGlzdChwaW5pX29yaWdpbl9hc3ltLCBwaW5pX29yaWdpbl9hc3ltLCBwaW5pX3NjYWxlLCAKICAgICAgICAgICAgICAgcGluaV9vcmlnaW5fYXN5bSwgcGluaV9vcmlnaW5fYXN5bSkKCiAgZnVuX2RmIDwtIGRhdGEgJT4lIAogICAgZGlzdGluY3QocmVmZXJlbmNlcykgJT4lIAogICAgYXJyYW5nZShyZWZlcmVuY2VzKSAlPiUgCiAgICBiaW5kX2NvbHModGliYmxlKGZ1biA9IGMoZnVuXzEsIGZ1bl8yKSkpIAoKICBxdWlja3BzeShkYXRhLCBvcmllbnRhdGlvbiwgcmVzcG9uc2UsIGZ1biA9IGZ1bl9kZiwgeG1pbiA9IC00LCB4bWF4ID0gNCwKICAgICAgICAgICBwYXJpbmkgPSBwaW5pLCBib290c3RyYXAgPSAibm9uZSIsIGdyb3VwaW5nID0gLihyZWZlcmVuY2VzKSwKICAgICAgICAgICB0aHJlc2hvbGQgPSBGQUxTRSkKfQoKZml0X2FzeW1fZnVsbF9zeW1fY3JpdF9mdW4gPC0gZnVuY3Rpb24oZGF0YSkgewogIAogIGZ1bl8xIDwtIGZ1bmN0aW9uKHgsIHApIHBub3JtKHgsIHBbMV0gLSBwWzJdLCBwWzNdKSAtIHBub3JtKHgsIHBbMV0gKyBwWzJdLCBwWzNdKQogIGZ1bl8yIDwtIGZ1bmN0aW9uKHgsIHApIHBub3JtKHgsIHBbMV0gLSBwWzRdLCBwWzVdKSAtIHBub3JtKHgsIHBbMV0gKyBwWzRdLCBwWzVdKQogIAogIHBpbmkgPC0gbGlzdChwaW5pX29yaWdpbl9hc3ltLCBwaW5pX29yaWdpbl9hc3ltLCBwaW5pX3NjYWxlLCAKICAgICAgICAgICAgICAgcGluaV9vcmlnaW5fYXN5bSwgcGluaV9zY2FsZSkKCiAgZnVuX2RmIDwtIGRhdGEgJT4lIAogICAgZGlzdGluY3QocmVmZXJlbmNlcykgJT4lIAogICAgYXJyYW5nZShyZWZlcmVuY2VzKSAlPiUgCiAgICBiaW5kX2NvbHModGliYmxlKGZ1biA9IGMoZnVuXzEsIGZ1bl8yKSkpIAoKICBxdWlja3BzeShkYXRhLCBvcmllbnRhdGlvbiwgcmVzcG9uc2UsIGZ1biA9IGZ1bl9kZiwgeG1pbiA9IC00LCB4bWF4ID0gNCwKICAgICAgICAgICBwYXJpbmkgPSBwaW5pLCBib290c3RyYXAgPSAibm9uZSIsIGdyb3VwaW5nID0gLihyZWZlcmVuY2VzKSwKICAgICAgICAgICB0aHJlc2hvbGQgPSBGQUxTRSkKfQoKZml0X2FzeW1fZnVsbF9zeW1fY3JpdF9zYW1lX2Z1biA8LSBmdW5jdGlvbihkYXRhKSB7CiAgCiAgZnVuXzEgPC0gZnVuY3Rpb24oeCwgcCkgcG5vcm0oeCwgcFsxXSAtIHBbMl0sIHBbM10pIC0gcG5vcm0oeCwgcFsxXSArIHBbMl0sIHBbM10pCiAgZnVuXzIgPC0gZnVuY3Rpb24oeCwgcCkgcG5vcm0oeCwgcFsxXSAtIHBbMl0sIHBbNF0pIC0gcG5vcm0oeCwgcFsxXSArIHBbMl0sIHBbNF0pCiAgCiAgcGluaSA8LSBsaXN0KHBpbmlfb3JpZ2luX2FzeW0sIHBpbmlfb3JpZ2luX2FzeW0sIHBpbmlfc2NhbGUsIAogICAgICAgICAgICAgICBwaW5pX3NjYWxlKQoKICBmdW5fZGYgPC0gZGF0YSAlPiUgCiAgICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgICBhcnJhbmdlKHJlZmVyZW5jZXMpICU+JSAKICAgIGJpbmRfY29scyh0aWJibGUoZnVuID0gYyhmdW5fMSwgZnVuXzIpKSkgCgogIHF1aWNrcHN5KGRhdGEsIG9yaWVudGF0aW9uLCByZXNwb25zZSwgZnVuID0gZnVuX2RmLCB4bWluID0gLTQsIHhtYXggPSA0LAogICAgICAgICAgIHBhcmluaSA9IHBpbmksIGJvb3RzdHJhcCA9ICJub25lIiwgZ3JvdXBpbmcgPSAuKHJlZmVyZW5jZXMpLAogICAgICAgICAgIHRocmVzaG9sZCA9IEZBTFNFKQp9CgpmaXRfYXN5bV9mdWxsX3N5bV9jcml0X3NhbWVfemVyb19mdW4gPC0gZnVuY3Rpb24oZGF0YSkgewogIAogIGZ1bl8xIDwtIGZ1bmN0aW9uKHgsIHApIHBub3JtKHgsIC0gcFsxXSwgcFsyXSkgLSBwbm9ybSh4LCBwWzFdLCBwWzJdKQogIGZ1bl8yIDwtIGZ1bmN0aW9uKHgsIHApIHBub3JtKHgsIC0gcFsxXSwgcFszXSkgLSBwbm9ybSh4LCBwWzFdLCBwWzNdKQogIAogIHBpbmkgPC0gbGlzdChwaW5pX29yaWdpbl9hc3ltLCBwaW5pX3NjYWxlLCBwaW5pX3NjYWxlKQoKICBmdW5fZGYgPC0gZGF0YSAlPiUgCiAgICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgICBhcnJhbmdlKHJlZmVyZW5jZXMpICU+JSAKICAgIGJpbmRfY29scyh0aWJibGUoZnVuID0gYyhmdW5fMSwgZnVuXzIpKSkgCgogIHF1aWNrcHN5KGRhdGEsIG9yaWVudGF0aW9uLCByZXNwb25zZSwgZnVuID0gZnVuX2RmLCB4bWluID0gLTQsIHhtYXggPSA0LAogICAgICAgICAgIHBhcmluaSA9IHBpbmksIGJvb3RzdHJhcCA9ICJub25lIiwgZ3JvdXBpbmcgPSAuKHJlZmVyZW5jZXMpLAogICAgICAgICAgIHRocmVzaG9sZCA9IEZBTFNFKQp9CgoKZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X2Z1biA8LSBmdW5jdGlvbihkYXRhKSB7CiAgCiAgZnVuXzEgPC0gZnVuY3Rpb24oeCwgcCkgcG5vcm0oeCwgcFsxXSAtIHBbMl0sIHBbM10pIC0gcG5vcm0oeCwgcFsxXSArIHBbMl0sIHBbM10pCiAgZnVuXzIgPC0gZnVuY3Rpb24oeCwgcCkgcG5vcm0oeCwgcFsxXSAtIHBbNF0sIHBbM10pIC0gcG5vcm0oeCwgcFsxXSArIHBbNF0sIHBbM10pCiAgCiAgcGluaSA8LSBsaXN0KHBpbmlfb3JpZ2luX2FzeW0sIHBpbmlfb3JpZ2luX2FzeW0sIHBpbmlfc2NhbGUsIAogICAgICAgICAgICAgICBwaW5pX29yaWdpbl9hc3ltKQoKICBmdW5fZGYgPC0gZGF0YSAlPiUgCiAgICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgICBhcnJhbmdlKHJlZmVyZW5jZXMpICU+JSAKICAgIGJpbmRfY29scyh0aWJibGUoZnVuID0gYyhmdW5fMSwgZnVuXzIpKSkgCgogIHF1aWNrcHN5KGRhdGEsIG9yaWVudGF0aW9uLCByZXNwb25zZSwgZnVuID0gZnVuX2RmLCB4bWluID0gLTQsIHhtYXggPSA0LAogICAgICAgICAgIHBhcmluaSA9IHBpbmksIGJvb3RzdHJhcCA9ICJub25lIiwgZ3JvdXBpbmcgPSAuKHJlZmVyZW5jZXMpLAogICAgICAgICAgIHRocmVzaG9sZCA9IEZBTFNFKQp9CgpmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfemVyb19mdW4gPC0gZnVuY3Rpb24oZGF0YSkgewogIAogIGZ1bl8xIDwtIGZ1bmN0aW9uKHgsIHApIHBub3JtKHgsIC0gcFsxXSwgcFsyXSkgLSBwbm9ybSh4LHBbMV0sIHBbMl0pCiAgZnVuXzIgPC0gZnVuY3Rpb24oeCwgcCkgcG5vcm0oeCwgLSBwWzNdLCBwWzJdKSAtIHBub3JtKHgsIHBbM10sIHBbMl0pCiAgCiAgcGluaSA8LSBsaXN0KHBpbmlfb3JpZ2luX2FzeW0sIHBpbmlfc2NhbGUsIAogICAgICAgICAgICAgICBwaW5pX29yaWdpbl9hc3ltKQoKICBmdW5fZGYgPC0gZGF0YSAlPiUgCiAgICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgICBhcnJhbmdlKHJlZmVyZW5jZXMpICU+JSAKICAgIGJpbmRfY29scyh0aWJibGUoZnVuID0gYyhmdW5fMSwgZnVuXzIpKSkgCgogIHF1aWNrcHN5KGRhdGEsIG9yaWVudGF0aW9uLCByZXNwb25zZSwgZnVuID0gZnVuX2RmLCB4bWluID0gLTQsIHhtYXggPSA0LAogICAgICAgICAgIHBhcmluaSA9IHBpbmksIGJvb3RzdHJhcCA9ICJub25lIiwgZ3JvdXBpbmcgPSAuKHJlZmVyZW5jZXMpLAogICAgICAgICAgIHRocmVzaG9sZCA9IEZBTFNFKQp9CgpmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV9mdW4gPC0gZnVuY3Rpb24oZGF0YSkgewogIAogIGZ1bl8xIDwtIGZ1bmN0aW9uKHgsIHApIHBub3JtKHgsIHBbMV0gLSBwWzJdLCBwWzNdKSAtIHBub3JtKHgsIHBbMV0gKyBwWzJdLCBwWzNdKQogIGZ1bl8yIDwtIGZ1bmN0aW9uKHgsIHApIHBub3JtKHgsIHBbMV0gLSBwWzJdLCBwWzNdKSAtIHBub3JtKHgsIHBbMV0gKyBwWzJdLCBwWzNdKQogIAogIHBpbmkgPC0gbGlzdChwaW5pX29yaWdpbl9hc3ltLCBwaW5pX29yaWdpbl9hc3ltLCBwaW5pX3NjYWxlKQoKICBmdW5fZGYgPC0gZGF0YSAlPiUgCiAgICBkaXN0aW5jdChyZWZlcmVuY2VzKSAlPiUgCiAgICBhcnJhbmdlKHJlZmVyZW5jZXMpICU+JSAKICAgIGJpbmRfY29scyh0aWJibGUoZnVuID0gYyhmdW5fMSwgZnVuXzIpKSkgCgogIHF1aWNrcHN5KGRhdGEsIG9yaWVudGF0aW9uLCByZXNwb25zZSwgZnVuID0gZnVuX2RmLCB4bWluID0gLTQsIHhtYXggPSA0LAogICAgICAgICAgIHBhcmluaSA9IHBpbmksIGJvb3RzdHJhcCA9ICJub25lIiwgZ3JvdXBpbmcgPSAuKHJlZmVyZW5jZXMpLAogICAgICAgICAgIHRocmVzaG9sZCA9IEZBTFNFKQp9CgpmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV96ZXJvX2Z1biA8LSBmdW5jdGlvbihkYXRhKSB7CiAgCiAgZnVuXzEgPC0gZnVuY3Rpb24oeCwgcCkgcG5vcm0oeCwgLSBwWzFdLCBwWzJdKSAtIHBub3JtKHgsIHBbMV0sIHBbMl0pCiAgZnVuXzIgPC0gZnVuY3Rpb24oeCwgcCkgcG5vcm0oeCwgLSBwWzFdLCBwWzJdKSAtIHBub3JtKHgsIHBbMV0sIHBbMl0pCiAgCiAgcGluaSA8LSBsaXN0KHBpbmlfb3JpZ2luX2FzeW0sIHBpbmlfc2NhbGUpCgogIGZ1bl9kZiA8LSBkYXRhICU+JSAKICAgIGRpc3RpbmN0KHJlZmVyZW5jZXMpICU+JSAKICAgIGFycmFuZ2UocmVmZXJlbmNlcykgJT4lIAogICAgYmluZF9jb2xzKHRpYmJsZShmdW4gPSBjKGZ1bl8xLCBmdW5fMikpKSAKCiAgcXVpY2twc3koZGF0YSwgb3JpZW50YXRpb24sIHJlc3BvbnNlLCBmdW4gPSBmdW5fZGYsIHhtaW4gPSAtNCwgeG1heCA9IDQsCiAgICAgICAgICAgcGFyaW5pID0gcGluaSwgYm9vdHN0cmFwID0gIm5vbmUiLCBncm91cGluZyA9IC4ocmVmZXJlbmNlcyksCiAgICAgICAgICAgdGhyZXNob2xkID0gRkFMU0UpCn0KCmZpdF9hc3ltX2Z1bGxfZnVuX3plcm8gPC0gZnVuY3Rpb24oZGF0YSkgewogIAogIGZ1bl8xIDwtIGZ1bmN0aW9uKHgsIHApIHBub3JtKHgsIC0gcFsxXSwgcFsyXSkgLSBwbm9ybSh4LCBwWzFdLCBwWzJdKQogIGZ1bl8yIDwtIGZ1bmN0aW9uKHgsIHApIHBub3JtKHgsIC0gcFszXSwgcFs0XSkgLSBwbm9ybSh4LCBwWzNdLCBwWzRdKQogIAogIHBpbmkgPC0gbGlzdChwaW5pX29yaWdpbl9hc3ltLCBwaW5pX3NjYWxlLCAKICAgICAgICAgICAgICAgcGluaV9vcmlnaW5fYXN5bSwgcGluaV9zY2FsZSkKCiAgZnVuX2RmIDwtIGRhdGEgJT4lIAogICAgZGlzdGluY3QocmVmZXJlbmNlcykgJT4lIAogICAgYXJyYW5nZShyZWZlcmVuY2VzKSAlPiUgCiAgICBiaW5kX2NvbHModGliYmxlKGZ1biA9IGMoZnVuXzEsIGZ1bl8yKSkpIAoKICBxdWlja3BzeShkYXRhLCBvcmllbnRhdGlvbiwgcmVzcG9uc2UsIGZ1biA9IGZ1bl9kZiwgeG1pbiA9IC00LCB4bWF4ID0gNCwKICAgICAgICAgICBwYXJpbmkgPSBwaW5pLCBib290c3RyYXAgPSAibm9uZSIsIGdyb3VwaW5nID0gLihyZWZlcmVuY2VzKSwKICAgICAgICAgICB0aHJlc2hvbGQgPSBGQUxTRSkKfQoKCgoKZml0X2FzeW1fYmVzdCA8LSBkYXRfYXN5bSAlPiUgCiAgZ3JvdXBfYnkoc3ViamVjdCwgdmVydGljYWwpICU+JSAKICBuZXN0KCkgJT4lIAogIG11dGF0ZShmaXRfYXN5bV9mdWxsID0gbWFwKGRhdGEsIGZpdF9hc3ltX2Z1bGxfZnVuKSwKICAgICAgICAgZml0X2FzeW1fZnVsbF9zeW1fY3JpdCA9IG1hcChkYXRhLCBmaXRfYXN5bV9mdWxsX3N5bV9jcml0X2Z1biksCiAgICAgICAgIGZpdF9hc3ltX2Z1bGxfc3ltX2NyaXRfc2FtZSA9IG1hcChkYXRhLCBmaXRfYXN5bV9mdWxsX3N5bV9jcml0X3NhbWVfZnVuKSwKICAgICAgICAgZml0X2FzeW1fZnVsbF9zeW1fY3JpdF9zYW1lX3plcm8gPSBtYXAoZGF0YSwgZml0X2FzeW1fZnVsbF9zeW1fY3JpdF9zYW1lX3plcm9fZnVuKSwKICAgICAgICAgZml0X2FzeW1fZnVsbF96ZXJvID0gbWFwKGRhdGEsIGZpdF9hc3ltX2Z1bGxfZnVuX3plcm8pLAogICAgICAgICBmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGUgPSBtYXAoZGF0YSwgZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX2Z1biksCiAgICAgICAgIGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdCA9IG1hcChkYXRhLCBmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfZnVuKSwKICAgICAgICAgZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3plcm8gPSBtYXAoZGF0YSwgZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3plcm9fZnVuKSwKICAgICAgICAgZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWUgPSBtYXAoZGF0YSwgZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWVfZnVuKSwKICAgICAgICAgZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWVfemVybyA9IG1hcChkYXRhLCBmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV96ZXJvX2Z1bikpICU+JSAKICAgICAgIyAgIGZpdF9hc3ltX3plcm8gPSBtYXAoZGF0YSwgZml0X2FzeW1femVyb19mdW4pLAogICAgICAgIyAgZml0X2FzeW1fcCA9IG1hcChkYXRhLCBmaXRfYXN5bV9wX2Z1biksCiAgICAgICAjICBmaXRfYXN5bV9kID0gbWFwKGRhdGEsIGZpdF9hc3ltX2RfZnVuKSkgJT4lIAogIHNlbGVjdCgtZGF0YSkKYGBgCgojIyMgRnVsbApgYGB7ciBmaWcuaGVpZ2h0PTE4LCBmaWcud2lkdGg9MTV9CmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gdmVydGljYWwsIG5jb2wgPSA2KSArCiAgZ2VvbV9wb2ludChkYXRhID0gZml0X2FzeW1fYmVzdCAlPiUgCiAgICAgICAgICAgICAgIG11dGF0ZSh0ZW1wID0gbWFwKGZpdF9hc3ltX2Z1bGwsICJhdmVyYWdlcyIpKSAlPiUgCiAgICAgICAgICAgICAgIHNlbGVjdChzdWJqZWN0LCB2ZXJ0aWNhbCwgdGVtcCkgJT4lIAogICAgICAgICAgICAgICB1bm5lc3QodGVtcCksIAogICAgICAgICAgICAgYWVzKHggPSBvcmllbnRhdGlvbiwgeSA9IHByb2IsIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICBnZW9tX2xpbmUoZGF0YSA9IGZpdF9hc3ltX2Jlc3QgJT4lIAogICAgICAgICAgICAgICBtdXRhdGUodGVtcCA9IG1hcChmaXRfYXN5bV9mdWxsLCAiY3VydmVzIikpICU+JSAKICAgICAgICAgICAgICAgc2VsZWN0KHN1YmplY3QsIHZlcnRpY2FsLCB0ZW1wKSAlPiUgCiAgICAgICAgICAgICAgIHVubmVzdCh0ZW1wKSwgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKIyMjIEZ1bGwgc2FtZSBzbG9wZQpgYGB7ciBmaWcuaGVpZ2h0PTE4LCBmaWcud2lkdGg9MTV9CmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gdmVydGljYWwsIG5jb2wgPSA2KSArCiAgZ2VvbV9wb2ludChkYXRhID0gZml0X2FzeW1fYmVzdCAlPiUgCiAgICAgICAgICAgICAgIG11dGF0ZSh0ZW1wID0gbWFwKGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZSwgImF2ZXJhZ2VzIikpICU+JSAKICAgICAgICAgICAgICAgc2VsZWN0KHN1YmplY3QsIHZlcnRpY2FsLCB0ZW1wKSAlPiUgCiAgICAgICAgICAgICAgIHVubmVzdCh0ZW1wKSwgCiAgICAgICAgICAgICBhZXMoeCA9IG9yaWVudGF0aW9uLCB5ID0gcHJvYiwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIGdlb21fbGluZShkYXRhID0gZml0X2FzeW1fYmVzdCAlPiUgCiAgICAgICAgICAgICAgIG11dGF0ZSh0ZW1wID0gbWFwKGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZSwgImN1cnZlcyIpKSAlPiUgCiAgICAgICAgICAgICAgIHNlbGVjdChzdWJqZWN0LCB2ZXJ0aWNhbCwgdGVtcCkgJT4lIAogICAgICAgICAgICAgICB1bm5lc3QodGVtcCksIAogICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgdGhlbWVfZ3JleSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpIApgYGAKCiMjIyBGdWxsIHZzIGZ1bGwgc2FtZSBzbG9wZSAKCmBgYHtyfQphc3ltX2Z1bGxfdnNfZnVsbF9zYW1lX3Nsb3BlIDwtIGZpdF9hc3ltX2Jlc3QgJT4lIAogIGdyb3VwX2J5KHN1YmplY3QsIHZlcnRpY2FsKSAlPiUgCiAgdHJhbnNtdXRlKGZpdF9hc3ltX2Z1bGxfbG9nbGlrID0gbWFwKGZpdF9hc3ltX2Z1bGwsICJsb2dsaWtzIiksCiAgICAgICAgIGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9sb2dsaWsgPSBtYXAoZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlLCAibG9nbGlrcyIpLAogICAgICAgICBiZXN0ID0gbWFwMl9jaHIoZml0X2FzeW1fZnVsbF9sb2dsaWssIGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9sb2dsaWssIAogICAgICAgICAgICAgICAgICAgIH5tb2RlbF9zZWxlY3Rpb25fbHJ0KC54LCAueSkkYmVzdCkpCgphc3ltX2Z1bGxfdnNfZnVsbF9zYW1lX3Nsb3BlICU+JSAKICBncm91cF9ieShiZXN0KSAlPiUgCiAgY291bnQoKSAgICAgCiAgICAgICAgIApiZXN0X2FzeW1fZnVsbF9ub19zYW1lX3Nsb3BlIDwtIGFzeW1fZnVsbF92c19mdWxsX3NhbWVfc2xvcGUgJT4lIAogIGZpbHRlcihiZXN0ID09ICJmaXJzdCIpICU+JSAKICBzZWxlY3Qoc3ViamVjdCwgdmVydGljYWwpCgpiZXN0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlIDwtIGFzeW1fZnVsbF92c19mdWxsX3NhbWVfc2xvcGUgJT4lIAogIGZpbHRlcihiZXN0ID09ICJzZWNvbmQiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIHZlcnRpY2FsKQpgYGAKCgoKIyMjIEZ1bGwgbm8gc2FtZSBzbG9wZSBzeW0gY3JpdAoKYGBge3IgZmlnLmhlaWdodD0xOCwgZmlnLndpZHRoPTE1fQpnZ3Bsb3QoKSArIGZhY2V0X3dyYXAoc3ViamVjdCB+IHZlcnRpY2FsLCBuY29sID0gNikgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpdF9hc3ltX2Jlc3QgJT4lIAogICAgICAgICAgICAgICBtdXRhdGUodGVtcCA9IG1hcChmaXRfYXN5bV9mdWxsX3N5bV9jcml0LCAiYXZlcmFnZXMiKSkgJT4lIAogICAgICAgICAgICAgICBzZWxlY3Qoc3ViamVjdCwgdmVydGljYWwsIHRlbXApICU+JSAKICAgICAgICAgICAgICAgdW5uZXN0KHRlbXApLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBmaXRfYXN5bV9iZXN0ICU+JSAKICAgICAgICAgICAgICAgbXV0YXRlKHRlbXAgPSBtYXAoZml0X2FzeW1fZnVsbF9zeW1fY3JpdCwgImN1cnZlcyIpKSAlPiUgCiAgICAgICAgICAgICAgIHNlbGVjdChzdWJqZWN0LCB2ZXJ0aWNhbCwgdGVtcCkgJT4lIAogICAgICAgICAgICAgICB1bm5lc3QodGVtcCksIAogICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgdGhlbWVfZ3JleSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpIApgYGAKCiMjIyBGdWxsIG5vIHNhbWUgc2xvcGUgdnMgZnVsbCBubyBzYW1lIHNsb3BlIHN5bSBjcml0IAoKYGBge3J9CmFzeW1fZnVsbF9ub19zYW1lX3Nsb3BlX3ZzX2Z1bGxfbm9fc2FtZV9zbG9wZV9zeW1fY3JpdCA8LSBmaXRfYXN5bV9iZXN0ICU+JSAKICBncm91cF9ieShzdWJqZWN0LCB2ZXJ0aWNhbCkgJT4lIAogIHRyYW5zbXV0ZShmaXRfYXN5bV9mdWxsX2xvZ2xpayA9IG1hcChmaXRfYXN5bV9mdWxsLCAibG9nbGlrcyIpLAogICAgICAgICBmaXRfYXN5bV9mdWxsX3N5bV9jcml0X2xvZ2xpayA9IG1hcChmaXRfYXN5bV9mdWxsX3N5bV9jcml0LCAibG9nbGlrcyIpLAogICAgICAgICBiZXN0ID0gbWFwMl9jaHIoZml0X2FzeW1fZnVsbF9sb2dsaWssIGZpdF9hc3ltX2Z1bGxfc3ltX2NyaXRfbG9nbGlrLCAKICAgICAgICAgICAgICAgICAgICB+bW9kZWxfc2VsZWN0aW9uX2xydCgueCwgLnkpJGJlc3QpKQoKYXN5bV9mdWxsX25vX3NhbWVfc2xvcGVfdnNfZnVsbF9ub19zYW1lX3Nsb3BlX3N5bV9jcml0ICU+JSAKICBzZW1pX2pvaW4oYmVzdF9hc3ltX2Z1bGxfbm9fc2FtZV9zbG9wZSkgJT4lIAogIGdyb3VwX2J5KGJlc3QpICU+JSAKICBjb3VudCgpICAgICAKICAgICAgICAgCgpiZXN0X2FzeW1fZnVsbF9ub19zYW1lX3Nsb3BlX3N5bV9jcml0IDwtIGFzeW1fZnVsbF9ub19zYW1lX3Nsb3BlX3ZzX2Z1bGxfbm9fc2FtZV9zbG9wZV9zeW1fY3JpdCAlPiUgCiAgc2VtaV9qb2luKGJlc3RfYXN5bV9mdWxsX25vX3NhbWVfc2xvcGUpICU+JSAKICBmaWx0ZXIoYmVzdCA9PSAic2Vjb25kIikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCB2ZXJ0aWNhbCkKYGBgCgojIyMgRnVsbCBubyBzYW1lIHNsb3BlIHN5bSBjcml0IHNhbWUgCgpgYGB7ciBmaWcuaGVpZ2h0PTE4LCBmaWcud2lkdGg9MTV9CmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gdmVydGljYWwsIG5jb2wgPSA2KSArCiAgZ2VvbV9wb2ludChkYXRhID0gZml0X2FzeW1fYmVzdCAlPiUgCiAgICAgICAgICAgICAgIG11dGF0ZSh0ZW1wID0gbWFwKGZpdF9hc3ltX2Z1bGxfc3ltX2NyaXRfc2FtZSwgImF2ZXJhZ2VzIikpICU+JSAKICAgICAgICAgICAgICAgc2VsZWN0KHN1YmplY3QsIHZlcnRpY2FsLCB0ZW1wKSAlPiUgCiAgICAgICAgICAgICAgIHVubmVzdCh0ZW1wKSwgCiAgICAgICAgICAgICBhZXMoeCA9IG9yaWVudGF0aW9uLCB5ID0gcHJvYiwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIGdlb21fbGluZShkYXRhID0gZml0X2FzeW1fYmVzdCAlPiUgCiAgICAgICAgICAgICAgIG11dGF0ZSh0ZW1wID0gbWFwKGZpdF9hc3ltX2Z1bGxfc3ltX2NyaXRfc2FtZSwgImN1cnZlcyIpKSAlPiUgCiAgICAgICAgICAgICAgIHNlbGVjdChzdWJqZWN0LCB2ZXJ0aWNhbCwgdGVtcCkgJT4lIAogICAgICAgICAgICAgICB1bm5lc3QodGVtcCksIAogICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgdGhlbWVfZ3JleSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpIApgYGAKCiMjIyBGdWxsIG5vIHNhbWUgc2xvcGUgc3ltIGNyaXQgdnMgZnVsbCBubyBzYW1lIHNsb3BlIHN5bSBjcml0IHNhbWUgCgpgYGB7cn0KYXN5bV9mdWxsX25vX3NhbWVfc2xvcGVfc3ltX2NyaXRfdnNfZnVsbF9ub19zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWUgPC0gZml0X2FzeW1fYmVzdCAlPiUgCiAgZ3JvdXBfYnkoc3ViamVjdCwgdmVydGljYWwpICU+JSAKICB0cmFuc211dGUoZml0X2FzeW1fZnVsbF9zeW1fY3JpdF9sb2dsaWsgPSBtYXAoZml0X2FzeW1fZnVsbF9zeW1fY3JpdCwgImxvZ2xpa3MiKSwKICAgICAgICAgZml0X2FzeW1fZnVsbF9zeW1fY3JpdF9zYW1lX2xvZ2xpayA9IG1hcChmaXRfYXN5bV9mdWxsX3N5bV9jcml0X3NhbWUsICJsb2dsaWtzIiksCiAgICAgICAgIGJlc3QgPSBtYXAyX2NocihmaXRfYXN5bV9mdWxsX3N5bV9jcml0X2xvZ2xpaywgZml0X2FzeW1fZnVsbF9zeW1fY3JpdF9zYW1lX2xvZ2xpaywgCiAgICAgICAgICAgICAgICAgICAgfm1vZGVsX3NlbGVjdGlvbl9scnQoLngsIC55KSRiZXN0KSkKCmFzeW1fZnVsbF9ub19zYW1lX3Nsb3BlX3N5bV9jcml0X3ZzX2Z1bGxfbm9fc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lICU+JSAKICBzZW1pX2pvaW4oYmVzdF9hc3ltX2Z1bGxfbm9fc2FtZV9zbG9wZV9zeW1fY3JpdCkgJT4lIAogIGdyb3VwX2J5KGJlc3QpICU+JSAKICBjb3VudCgpICAgICAKICAgICAgICAgCgpiZXN0X2FzeW1fZnVsbF9ub19zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWUgPC0gYXN5bV9mdWxsX25vX3NhbWVfc2xvcGVfc3ltX2NyaXRfdnNfZnVsbF9ub19zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWUgJT4lIAogIHNlbWlfam9pbihiZXN0X2FzeW1fZnVsbF9ub19zYW1lX3Nsb3BlX3N5bV9jcml0KSAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gInNlY29uZCIpICU+JSAKICBzZWxlY3Qoc3ViamVjdCwgdmVydGljYWwpCmBgYAoKIyMjIEZ1bGwgbm8gc2FtZSBzbG9wZSBzeW0gY3JpdCBzYW1lIHplcm8KCmBgYHtyIGZpZy5oZWlnaHQ9MTgsIGZpZy53aWR0aD0xNX0KZ2dwbG90KCkgKyBmYWNldF93cmFwKHN1YmplY3QgfiB2ZXJ0aWNhbCwgbmNvbCA9IDYpICsKICBnZW9tX3BvaW50KGRhdGEgPSBmaXRfYXN5bV9iZXN0ICU+JSAKICAgICAgICAgICAgICAgbXV0YXRlKHRlbXAgPSBtYXAoZml0X2FzeW1fZnVsbF9zeW1fY3JpdF9zYW1lX3plcm8sICJhdmVyYWdlcyIpKSAlPiUgCiAgICAgICAgICAgICAgIHNlbGVjdChzdWJqZWN0LCB2ZXJ0aWNhbCwgdGVtcCkgJT4lIAogICAgICAgICAgICAgICB1bm5lc3QodGVtcCksIAogICAgICAgICAgICAgYWVzKHggPSBvcmllbnRhdGlvbiwgeSA9IHByb2IsIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICBnZW9tX2xpbmUoZGF0YSA9IGZpdF9hc3ltX2Jlc3QgJT4lIAogICAgICAgICAgICAgICBtdXRhdGUodGVtcCA9IG1hcChmaXRfYXN5bV9mdWxsX3N5bV9jcml0X3NhbWVfemVybywgImN1cnZlcyIpKSAlPiUgCiAgICAgICAgICAgICAgIHNlbGVjdChzdWJqZWN0LCB2ZXJ0aWNhbCwgdGVtcCkgJT4lIAogICAgICAgICAgICAgICB1bm5lc3QodGVtcCksIAogICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgdGhlbWVfZ3JleSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpIApgYGAKCiMjIyBGdWxsIG5vIHNhbWUgc2xvcGUgc3ltIGNyaXQgc2FtZSB2cyBmdWxsIG5vIHNhbWUgc2xvcGUgc3ltIGNyaXQgc2FtZSB6ZXJvCgpgYGB7cn0KYXN5bV9mdWxsX25vX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV92c19mdWxsX25vX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV96ZXJvIDwtIGZpdF9hc3ltX2Jlc3QgJT4lIAogIGdyb3VwX2J5KHN1YmplY3QsIHZlcnRpY2FsKSAlPiUgCiAgdHJhbnNtdXRlKGZpdF9hc3ltX2Z1bGxfc3ltX2NyaXRfc2FtZV9sb2dsaWsgPSBtYXAoZml0X2FzeW1fZnVsbF9zeW1fY3JpdF9zYW1lLCAibG9nbGlrcyIpLAogICAgICAgICBmaXRfYXN5bV9mdWxsX3N5bV9jcml0X3NhbWVfemVyb19sb2dsaWsgPSBtYXAoZml0X2FzeW1fZnVsbF9zeW1fY3JpdF9zYW1lX3plcm8sICJsb2dsaWtzIiksCiAgICAgICAgIGJlc3QgPSBtYXAyX2NocihmaXRfYXN5bV9mdWxsX3N5bV9jcml0X3NhbWVfbG9nbGlrLCBmaXRfYXN5bV9mdWxsX3N5bV9jcml0X3NhbWVfemVyb19sb2dsaWssIAogICAgICAgICAgICAgICAgICAgIH5tb2RlbF9zZWxlY3Rpb25fbHJ0KC54LCAueSkkYmVzdCkpCgphc3ltX2Z1bGxfbm9fc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX3ZzX2Z1bGxfbm9fc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX3plcm8gJT4lIAogIHNlbWlfam9pbihiZXN0X2FzeW1fZnVsbF9ub19zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWUpICU+JSAKICBncm91cF9ieShiZXN0KSAlPiUgCiAgY291bnQoKSAgICAgCiAgICAgICAgIAojIyMgQWRkIHRvIHMgdnMgZApiZXN0X2FzeW1fZnVsbF9ub19zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWVfbm9femVybyA8LSBhc3ltX2Z1bGxfbm9fc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX3ZzX2Z1bGxfbm9fc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX3plcm8gJT4lCiAgc2VtaV9qb2luKGJlc3RfYXN5bV9mdWxsX25vX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZSkgJT4lIAogIGZpbHRlcihiZXN0ID09ICJmaXJzdCIpICU+JSAKICBzZWxlY3Qoc3ViamVjdCwgdmVydGljYWwpICU+JSAKICBtdXRhdGUoYmVzdCA9ICJyZXNwb25zZSIpCmBgYAoKIyMjIEZ1bGwgc2FtZSBzbG9wZSBzeW0gY3JpdAoKYGBge3IgZmlnLmhlaWdodD0xOCwgZmlnLndpZHRoPTE1fQpnZ3Bsb3QoKSArIGZhY2V0X3dyYXAoc3ViamVjdCB+IHZlcnRpY2FsLCBuY29sID0gNikgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpdF9hc3ltX2Jlc3QgJT4lIAogICAgICAgICAgICAgICBtdXRhdGUodGVtcCA9IG1hcChmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXQsICJhdmVyYWdlcyIpKSAlPiUgCiAgICAgICAgICAgICAgIHNlbGVjdChzdWJqZWN0LCB2ZXJ0aWNhbCwgdGVtcCkgJT4lIAogICAgICAgICAgICAgICB1bm5lc3QodGVtcCksIAogICAgICAgICAgICAgYWVzKHggPSBvcmllbnRhdGlvbiwgeSA9IHByb2IsIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICBnZW9tX2xpbmUoZGF0YSA9IGZpdF9hc3ltX2Jlc3QgJT4lIAogICAgICAgICAgICAgICBtdXRhdGUodGVtcCA9IG1hcChmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXQsICJjdXJ2ZXMiKSkgJT4lIAogICAgICAgICAgICAgICBzZWxlY3Qoc3ViamVjdCwgdmVydGljYWwsIHRlbXApICU+JSAKICAgICAgICAgICAgICAgdW5uZXN0KHRlbXApLCAKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIHRoZW1lX2dyZXkoKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSAKYGBgCgoKIyMjIEZ1bGwgc2FtZSBzbG9wZSB2cyBmdWxsIHNhbWUgc2xvcGUgc3ltIGNyaXQgCgpgYGB7cn0KYXN5bV9mdWxsX3NhbWVfc2xvcGVfdnNfZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0IDwtIGZpdF9hc3ltX2Jlc3QgJT4lIAogIGdyb3VwX2J5KHN1YmplY3QsIHZlcnRpY2FsKSAlPiUgCiAgdHJhbnNtdXRlKGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9sb2dsaWsgPSBtYXAoZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlLCAibG9nbGlrcyIpLAogICAgICAgICBmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfbG9nbGlrID0gbWFwKGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdCwgImxvZ2xpa3MiKSwKICAgICAgICAgYmVzdCA9IG1hcDJfY2hyKGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9sb2dsaWssIGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9sb2dsaWssIAogICAgICAgICAgICAgICAgICAgIH5tb2RlbF9zZWxlY3Rpb25fbHJ0KC54LCAueSkkYmVzdCkpCgphc3ltX2Z1bGxfc2FtZV9zbG9wZV92c19mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXQgJT4lIAogIHNlbWlfam9pbihiZXN0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlKSAlPiUgCiAgZ3JvdXBfYnkoYmVzdCkgJT4lIAogIGNvdW50KCkgICAgIAogICAgICAgICAKIyMjIEFkZCB0byBzIHZzIGQKYmVzdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9ub19zeW1fY3JpdCA8LSBhc3ltX2Z1bGxfc2FtZV9zbG9wZV92c19mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXQgJT4lCiAgc2VtaV9qb2luKGJlc3RfYXN5bV9mdWxsX3NhbWVfc2xvcGUpICU+JSAKICBmaWx0ZXIoYmVzdCA9PSAiZmlyc3QiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIHZlcnRpY2FsKSAlPiUgCiAgbXV0YXRlKGJlc3QgPSAibm8gc3ltIGNyaXQiKQoKYmVzdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdCA8LSBhc3ltX2Z1bGxfc2FtZV9zbG9wZV92c19mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXQgJT4lCiAgc2VtaV9qb2luKGJlc3RfYXN5bV9mdWxsX3NhbWVfc2xvcGUpICU+JSAKICBmaWx0ZXIoYmVzdCA9PSAic2Vjb25kIikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCB2ZXJ0aWNhbCkgCmBgYAoKIyMjIEZ1bGwgc2FtZSBzbG9wZSBzeW0gY3JpdCBzYW1lIAoKYGBge3IgZmlnLmhlaWdodD0xOCwgZmlnLndpZHRoPTE1fQpnZ3Bsb3QoKSArIGZhY2V0X3dyYXAoc3ViamVjdCB+IHZlcnRpY2FsLCBuY29sID0gNikgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpdF9hc3ltX2Jlc3QgJT4lIAogICAgICAgICAgICAgICBtdXRhdGUodGVtcCA9IG1hcChmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZSwgImF2ZXJhZ2VzIikpICU+JSAKICAgICAgICAgICAgICAgc2VsZWN0KHN1YmplY3QsIHZlcnRpY2FsLCB0ZW1wKSAlPiUgCiAgICAgICAgICAgICAgIHVubmVzdCh0ZW1wKSwgCiAgICAgICAgICAgICBhZXMoeCA9IG9yaWVudGF0aW9uLCB5ID0gcHJvYiwgY29sb3IgPSByZWZlcmVuY2VzKSkgKwogIGdlb21fbGluZShkYXRhID0gZml0X2FzeW1fYmVzdCAlPiUgCiAgICAgICAgICAgICAgIG11dGF0ZSh0ZW1wID0gbWFwKGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lLCAiY3VydmVzIikpICU+JSAKICAgICAgICAgICAgICAgc2VsZWN0KHN1YmplY3QsIHZlcnRpY2FsLCB0ZW1wKSAlPiUgCiAgICAgICAgICAgICAgIHVubmVzdCh0ZW1wKSwgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICB0aGVtZV9ncmV5KCkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgCmBgYAoKCiMjIyBGdWxsIHNhbWUgc2xvcGUgc3ltIGNyaXQgdnMgZnVsbCBzYW1lIHNsb3BlIHN5bSBjcml0IHNhbWUKCmBgYHtyfQphc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF92c19mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZSA8LSBmaXRfYXN5bV9iZXN0ICU+JSAKICBncm91cF9ieShzdWJqZWN0LCB2ZXJ0aWNhbCkgJT4lIAogIHRyYW5zbXV0ZShmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfbG9nbGlrID0gbWFwKGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdCwgImxvZ2xpa3MiKSwKICAgICAgICAgZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWVfbG9nbGlrID0gbWFwKGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lLCAibG9nbGlrcyIpLAogICAgICAgICBiZXN0ID0gbWFwMl9jaHIoZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X2xvZ2xpaywgZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWVfbG9nbGlrLCAKICAgICAgICAgICAgICAgICAgICB+bW9kZWxfc2VsZWN0aW9uX2xydCgueCwgLnkpJGJlc3QpKQoKYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfdnNfZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWUgJT4lIAogIHNlbWlfam9pbihiZXN0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0KSAlPiUgCiAgZ3JvdXBfYnkoYmVzdCkgJT4lIAogIGNvdW50KCkgICAgIAogICAgICAgICAKYmVzdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9ub19zYW1lIDwtIGFzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3ZzX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lICU+JQogIHNlbWlfam9pbihiZXN0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0KSAlPiUgCiAgZmlsdGVyKGJlc3QgPT0gImZpcnN0IikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCB2ZXJ0aWNhbCkgCgpiZXN0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWUgPC0gYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfdnNfZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWUgJT4lCiAgc2VtaV9qb2luKGJlc3RfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXQpICU+JSAKICBmaWx0ZXIoYmVzdCA9PSAic2Vjb25kIikgJT4lIAogIHNlbGVjdChzdWJqZWN0LCB2ZXJ0aWNhbCkgCmBgYAoKIyMjIEZ1bGwgc2FtZSBzbG9wZSBzeW0gY3JpdCBubyBzYW1lIHplcm8KCmBgYHtyIGZpZy5oZWlnaHQ9MTgsIGZpZy53aWR0aD0xNX0KZ2dwbG90KCkgKyBmYWNldF93cmFwKHN1YmplY3QgfiB2ZXJ0aWNhbCwgbmNvbCA9IDYpICsKICBnZW9tX3BvaW50KGRhdGEgPSBmaXRfYXN5bV9iZXN0ICU+JSAKICAgICAgICAgICAgICAgbXV0YXRlKHRlbXAgPSBtYXAoZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3plcm8sICJhdmVyYWdlcyIpKSAlPiUgCiAgICAgICAgICAgICAgIHNlbGVjdChzdWJqZWN0LCB2ZXJ0aWNhbCwgdGVtcCkgJT4lIAogICAgICAgICAgICAgICB1bm5lc3QodGVtcCksIAogICAgICAgICAgICAgYWVzKHggPSBvcmllbnRhdGlvbiwgeSA9IHByb2IsIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICBnZW9tX2xpbmUoZGF0YSA9IGZpdF9hc3ltX2Jlc3QgJT4lIAogICAgICAgICAgICAgICBtdXRhdGUodGVtcCA9IG1hcChmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfemVybywgImN1cnZlcyIpKSAlPiUgCiAgICAgICAgICAgICAgIHNlbGVjdChzdWJqZWN0LCB2ZXJ0aWNhbCwgdGVtcCkgJT4lIAogICAgICAgICAgICAgICB1bm5lc3QodGVtcCksIAogICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgdGhlbWVfZ3JleSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpIApgYGAKCiMjIyBGdWxsIHNhbWUgc2xvcGUgc3ltIGNyaXQgbm8gc2FtZSB2cyBmdWxsIHNhbWUgc2xvcGUgc3ltIGNyaXQgbm8gc2FtZSB6ZXJvIAoKYGBge3J9CmFzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X25vX3NhbWVfdnNfZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X25vX3NhbWVfemVybyA8LSBmaXRfYXN5bV9iZXN0ICU+JSAKICBncm91cF9ieShzdWJqZWN0LCB2ZXJ0aWNhbCkgJT4lIAogIHRyYW5zbXV0ZShmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfbG9nbGlrID0gbWFwKGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdCwgImxvZ2xpa3MiKSwKICAgICAgICAgZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3plcm9fbG9nbGlrID0gbWFwKGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF96ZXJvLCAibG9nbGlrcyIpLAogICAgICAgICBiZXN0ID0gbWFwMl9jaHIoZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X2xvZ2xpaywgZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3plcm9fbG9nbGlrLCAKICAgICAgICAgICAgICAgICAgICB+bW9kZWxfc2VsZWN0aW9uX2xydCgueCwgLnkpJGJlc3QpKQoKYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfbm9fc2FtZV92c19mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfbm9fc2FtZV96ZXJvICU+JSAKICBzZW1pX2pvaW4oYmVzdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9ub19zYW1lKSAlPiUgCiAgZ3JvdXBfYnkoYmVzdCkgJT4lIAogIGNvdW50KCkgICAgIAogICAgICAgICAKIyMjIEFkZCB0byBzIHZzIGQKYmVzdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9ub19zYW1lX25vX3plcm8gPC0gYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfbm9fc2FtZV92c19mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfbm9fc2FtZV96ZXJvICU+JQogIHNlbWlfam9pbihiZXN0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X25vX3NhbWUpICU+JSAKICBmaWx0ZXIoYmVzdCA9PSAiZmlyc3QiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIHZlcnRpY2FsKSAlPiUgCiAgbXV0YXRlKGJlc3QgPSAicmVzcG9uc2UiKQoKYGBgCgojIyMgRnVsbCBzYW1lIHNsb3BlIHN5bSBjcml0IHNhbWUgemVybwoKYGBge3IgZmlnLmhlaWdodD0xOCwgZmlnLndpZHRoPTE1fQpnZ3Bsb3QoKSArIGZhY2V0X3dyYXAoc3ViamVjdCB+IHZlcnRpY2FsLCBuY29sID0gNikgKwogIGdlb21fcG9pbnQoZGF0YSA9IGZpdF9hc3ltX2Jlc3QgJT4lIAogICAgICAgICAgICAgICBtdXRhdGUodGVtcCA9IG1hcChmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV96ZXJvLCAiYXZlcmFnZXMiKSkgJT4lIAogICAgICAgICAgICAgICBzZWxlY3Qoc3ViamVjdCwgdmVydGljYWwsIHRlbXApICU+JSAKICAgICAgICAgICAgICAgdW5uZXN0KHRlbXApLCAKICAgICAgICAgICAgIGFlcyh4ID0gb3JpZW50YXRpb24sIHkgPSBwcm9iLCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgZ2VvbV9saW5lKGRhdGEgPSBmaXRfYXN5bV9iZXN0ICU+JSAKICAgICAgICAgICAgICAgbXV0YXRlKHRlbXAgPSBtYXAoZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWVfemVybywgImN1cnZlcyIpKSAlPiUgCiAgICAgICAgICAgICAgIHNlbGVjdChzdWJqZWN0LCB2ZXJ0aWNhbCwgdGVtcCkgJT4lIAogICAgICAgICAgICAgICB1bm5lc3QodGVtcCksIAogICAgICAgICAgICBhZXMoeCA9IHgsIHkgPSB5LCBjb2xvciA9IHJlZmVyZW5jZXMpKSArCiAgdGhlbWVfZ3JleSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpIApgYGAKCiMjIyBGdWxsIHNhbWUgc2xvcGUgc3ltIGNyaXQgc2FtZSB2cyBmdWxsIHNhbWUgc2xvcGUgc3ltIGNyaXQgc2FtZSB6ZXJvIAoKYGBge3J9CmFzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWVfdnNfZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWVfemVybyA8LSBmaXRfYXN5bV9iZXN0ICU+JSAKICBncm91cF9ieShzdWJqZWN0LCB2ZXJ0aWNhbCkgJT4lIAogIHRyYW5zbXV0ZShmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV9sb2dsaWsgPSBtYXAoZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWUsICJsb2dsaWtzIiksCiAgICAgICAgIGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX3plcm9fbG9nbGlrID0gbWFwKGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX3plcm8sICJsb2dsaWtzIiksCiAgICAgICAgIGJlc3QgPSBtYXAyX2NocihmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV9sb2dsaWssIGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX3plcm9fbG9nbGlrLCAKICAgICAgICAgICAgICAgICAgICB+bW9kZWxfc2VsZWN0aW9uX2xydCgueCwgLnkpJGJlc3QpKQoKYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV92c19mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV96ZXJvICU+JSAKICBzZW1pX2pvaW4oYmVzdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lKSAlPiUgCiAgZ3JvdXBfYnkoYmVzdCkgJT4lIAogIGNvdW50KCkgICAgIAogICAgICAgICAKIyMjIEFkZCB0byBzIHZzIGQKYmVzdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX25vX3plcm8gPC0gYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV92c19mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV96ZXJvICU+JQogIHNlbWlfam9pbihiZXN0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWUpICU+JSAKICBmaWx0ZXIoYmVzdCA9PSAiZmlyc3QiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIHZlcnRpY2FsKSAlPiUgCiAgbXV0YXRlKGJlc3QgPSAic2Vuc29yeSIpCgojIyMgQWRkIHRvIHMgdnMgZApiZXN0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWVfemVybyA8LSBhc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX3ZzX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX3plcm8gJT4lCiAgc2VtaV9qb2luKGJlc3RfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZSkgJT4lIAogIGZpbHRlcihiZXN0ID09ICJzZWNvbmQiKSAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIHZlcnRpY2FsKSAlPiUgCiAgbXV0YXRlKGJlc3QgPSAiemVybyIpCgpgYGAKCiMjIyBBdmVyYWdlcywgY3VydmVzIGFuZCBwYXJhbWV0ZXJzIApgYGB7ciBmaWcuaGVpZ2h0PTIwLCBmaWcud2lkdGg9MTV9CgoKZml0X2FzeW1fYmVzdCAlPiUgCiAgZ3JvdXBfYnkoc3ViamVjdCwgdmVydGljYWwpICU+JSAKICB0cmFuc211dGUodGVtcCA9IG1hcChmaXRfYXN5bV9mdWxsX3N5bV9jcml0X3NhbWUsICJhdmVyYWdlcyIpKSAlPiUgCiAgdW5uZXN0KHRlbXApCiAgCiAgCmFzeW1fYXZlcmFnZXNfc192c19kIDwtIAogIChmaXRfYXN5bV9iZXN0ICU+JSAKICBncm91cF9ieShzdWJqZWN0LCB2ZXJ0aWNhbCkgJT4lIAogIHRyYW5zbXV0ZSh0ZW1wID0gbWFwKGZpdF9hc3ltX2Z1bGwsICJhdmVyYWdlcyIpKSAlPiUgCiAgdW5uZXN0KHRlbXApICU+JSBzZW1pX2pvaW4oYmVzdF9hc3ltX2Z1bGxfbm9fc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX25vX3plcm8pKSAlPiUgCiAgYmluZF9yb3dzKChmaXRfYXN5bV9iZXN0ICU+JSAKICBncm91cF9ieShzdWJqZWN0LCB2ZXJ0aWNhbCkgJT4lIAogIHRyYW5zbXV0ZSh0ZW1wID0gbWFwKGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZSwgImF2ZXJhZ2VzIikpICU+JSAKICB1bm5lc3QodGVtcCkgJT4lIHNlbWlfam9pbihiZXN0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX25vX3N5bV9jcml0KSkpICU+JSAKICBiaW5kX3Jvd3MoKGZpdF9hc3ltX2Jlc3QgJT4lIAogIGdyb3VwX2J5KHN1YmplY3QsIHZlcnRpY2FsKSAlPiUgCiAgdHJhbnNtdXRlKHRlbXAgPSBtYXAoZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlLCAiYXZlcmFnZXMiKSkgJT4lIAogIHVubmVzdCh0ZW1wKSAlPiUgc2VtaV9qb2luKGJlc3RfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfbm9fc2FtZV9ub196ZXJvKSkpICU+JSAgIAogIGJpbmRfcm93cygoZml0X2FzeW1fYmVzdCAlPiUgCiAgZ3JvdXBfYnkoc3ViamVjdCwgdmVydGljYWwpICU+JSAKICB0cmFuc211dGUodGVtcCA9IG1hcChmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGUsICJhdmVyYWdlcyIpKSAlPiUgCiAgdW5uZXN0KHRlbXApICU+JSBzZW1pX2pvaW4oYmVzdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX25vX3plcm8pKSkgJT4lIAogIGJpbmRfcm93cygoZml0X2FzeW1fYmVzdCAlPiUgCiAgZ3JvdXBfYnkoc3ViamVjdCwgdmVydGljYWwpICU+JSAKICB0cmFuc211dGUodGVtcCA9IG1hcChmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGUsICJhdmVyYWdlcyIpKSAlPiUgCiAgdW5uZXN0KHRlbXApICU+JSBzZW1pX2pvaW4oYmVzdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX3plcm8pKSkgCgphc3ltX2N1cnZlc19zX3ZzX2QgPC0gCiAgKGZpdF9hc3ltX2Jlc3QgJT4lIAogIGdyb3VwX2J5KHN1YmplY3QsIHZlcnRpY2FsKSAlPiUgCiAgdHJhbnNtdXRlKHRlbXAgPSBtYXAoZml0X2FzeW1fZnVsbCwgImN1cnZlcyIpKSAlPiUgCiAgdW5uZXN0KHRlbXApICU+JSBzZW1pX2pvaW4oYmVzdF9hc3ltX2Z1bGxfbm9fc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX25vX3plcm8pKSAlPiUgCiAgYmluZF9yb3dzKChmaXRfYXN5bV9iZXN0ICU+JSAKICBncm91cF9ieShzdWJqZWN0LCB2ZXJ0aWNhbCkgJT4lIAogIHRyYW5zbXV0ZSh0ZW1wID0gbWFwKGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZSwgImN1cnZlcyIpKSAlPiUgCiAgdW5uZXN0KHRlbXApICU+JSBzZW1pX2pvaW4oYmVzdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9ub19zeW1fY3JpdCkpKSAlPiUgCiAgYmluZF9yb3dzKChmaXRfYXN5bV9iZXN0ICU+JSAKICBncm91cF9ieShzdWJqZWN0LCB2ZXJ0aWNhbCkgJT4lIAogIHRyYW5zbXV0ZSh0ZW1wID0gbWFwKGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZSwgImN1cnZlcyIpKSAlPiUgCiAgdW5uZXN0KHRlbXApICU+JSBzZW1pX2pvaW4oYmVzdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9ub19zYW1lX25vX3plcm8pKSkgJT4lICAgCiAgYmluZF9yb3dzKChmaXRfYXN5bV9iZXN0ICU+JSAKICBncm91cF9ieShzdWJqZWN0LCB2ZXJ0aWNhbCkgJT4lIAogIHRyYW5zbXV0ZSh0ZW1wID0gbWFwKGZpdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZSwgImN1cnZlcyIpKSAlPiUgCiAgdW5uZXN0KHRlbXApICU+JSBzZW1pX2pvaW4oYmVzdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX25vX3plcm8pKSkgJT4lIAogIGJpbmRfcm93cygoZml0X2FzeW1fYmVzdCAlPiUgCiAgZ3JvdXBfYnkoc3ViamVjdCwgdmVydGljYWwpICU+JSAKICB0cmFuc211dGUodGVtcCA9IG1hcChmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGUsICJjdXJ2ZXMiKSkgJT4lIAogIHVubmVzdCh0ZW1wKSAlPiUgc2VtaV9qb2luKGJlc3RfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV96ZXJvKSkpIAoKYXN5bV9wYXJfc192c19kIDwtIAogIChmaXRfYXN5bV9iZXN0ICU+JSAKICBncm91cF9ieShzdWJqZWN0LCB2ZXJ0aWNhbCkgJT4lIAogIHRyYW5zbXV0ZSh0ZW1wID0gbWFwKGZpdF9hc3ltX2Z1bGwsICJwYXIiKSkgJT4lIAogIHVubmVzdCh0ZW1wKSAlPiUgc2VtaV9qb2luKGJlc3RfYXN5bV9mdWxsX25vX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV9ub196ZXJvKSkgJT4lIAogIGJpbmRfcm93cygoZml0X2FzeW1fYmVzdCAlPiUgCiAgZ3JvdXBfYnkoc3ViamVjdCwgdmVydGljYWwpICU+JSAKICB0cmFuc211dGUodGVtcCA9IG1hcChmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGUsICJwYXIiKSkgJT4lIAogIHVubmVzdCh0ZW1wKSAlPiUgc2VtaV9qb2luKGJlc3RfYXN5bV9mdWxsX3NhbWVfc2xvcGVfbm9fc3ltX2NyaXQpKSkgJT4lIAogIGJpbmRfcm93cygoZml0X2FzeW1fYmVzdCAlPiUgCiAgZ3JvdXBfYnkoc3ViamVjdCwgdmVydGljYWwpICU+JSAKICB0cmFuc211dGUodGVtcCA9IG1hcChmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGUsICJwYXIiKSkgJT4lIAogIHVubmVzdCh0ZW1wKSAlPiUgc2VtaV9qb2luKGJlc3RfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfbm9fc2FtZV9ub196ZXJvKSkpICU+JSAgIAogIGJpbmRfcm93cygoZml0X2FzeW1fYmVzdCAlPiUgCiAgZ3JvdXBfYnkoc3ViamVjdCwgdmVydGljYWwpICU+JSAKICB0cmFuc211dGUodGVtcCA9IG1hcChmaXRfYXN5bV9mdWxsX3NhbWVfc2xvcGUsICJwYXIiKSkgJT4lIAogIHVubmVzdCh0ZW1wKSAlPiUgc2VtaV9qb2luKGJlc3RfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV9ub196ZXJvKSkpICU+JSAKICBiaW5kX3Jvd3MoKGZpdF9hc3ltX2Jlc3QgJT4lIAogIGdyb3VwX2J5KHN1YmplY3QsIHZlcnRpY2FsKSAlPiUgCiAgdHJhbnNtdXRlKHRlbXAgPSBtYXAoZml0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlLCAicGFyIikpICU+JSAKICB1bm5lc3QodGVtcCkgJT4lIHNlbWlfam9pbihiZXN0X2FzeW1fZnVsbF9zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWVfemVybykpKSAKICAKYXN5bV9wYXJfc192c19kX2xvbmcgPC0gYXN5bV9wYXJfc192c19kICU+JSAKICBzcHJlYWQocGFybixwYXIpICU+JSAKICBtdXRhdGUocGZpcnN0ID0gcDEsIAogICAgICAgICBwc2Vjb25kID0gcDEgKyAuNSAqIChwNSAtIHA0KSwKICAgICAgICAgcHNlbnNvcnkgPSAuNSAqIChwZmlyc3QgKyBwc2Vjb25kKSwKICAgICAgICAgcGRlY2lzaW9uYWwgPSBwZmlyc3QgLSBwc2Vuc29yeSkKCmdncGxvdCgpICsgZmFjZXRfd3JhcChzdWJqZWN0IH4gdmVydGljYWwsIG5jb2wgPSA0KSArCiAgZ2VvbV9wb2ludChkYXRhID0gYXN5bV9hdmVyYWdlc19zX3ZzX2QsIAogICAgICAgICAgICAgYWVzKHggPSBvcmllbnRhdGlvbiwgeSA9IHByb2IsIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICBnZW9tX2xpbmUoZGF0YSA9IGFzeW1fY3VydmVzX3NfdnNfZCwgCiAgICAgICAgICAgIGFlcyh4ID0geCwgeSA9IHksIGNvbG9yID0gcmVmZXJlbmNlcykpICsKICAjIGdlb21fdmxpbmUoZGF0YSA9IGFzeW1fcGFyX3NfdnNfZF9sb25nLAogICMgICAgICAgICAgICBhZXMoeGludGVyY2VwdCA9IHBmaXJzdCwgbHR5ID0gInBmaXJzdCIpKSArCiAgIyBnZW9tX3ZsaW5lKGRhdGEgPSBhc3ltX3Bhcl9zX3ZzX2RfbG9uZywKICAjICAgICAgICAgICAgYWVzKHhpbnRlcmNlcHQgPSBwc2Vjb25kLCBsdHkgPSAicHNlY29uZCIpKSArCiAgICAjIGdlb21fdmxpbmUoZGF0YSA9IGFzeW1fcGFyX3NfdnNfZF9sb25nLAogICAgIyAgICAgICAgICBhZXMoeGludGVyY2VwdCA9IHBzZW5zb3J5LCBsdHkgPSAicHNlbnNvcnkiKSkgKwogICAgZ2VvbV92bGluZShkYXRhID0gYXN5bV9wYXJfc192c19kX2xvbmcsCiAgICAgICAgICAgICBhZXMoeGludGVyY2VwdCA9IHBzZW5zb3J5ICsgcGRlY2lzaW9uYWwsIGx0eSA9ICJwc2Vuc29yeSAgKyBwZGVjaXNpb25hbCIpKSArCiAgdGhlbWVfZ3JleSgpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpIAogCmBgYAoKCgojIyMjIEFkZCBhbGwgYmVzdApgYGB7cn0KCmJlc3RfYXN5bSA8LSBiZXN0X2FzeW1fZnVsbF9ub19zYW1lX3Nsb3BlX3N5bV9jcml0X3NhbWVfbm9femVybyAlPiUgCiAgYmluZF9yb3dzKGJlc3RfYXN5bV9mdWxsX3NhbWVfc2xvcGVfbm9fc3ltX2NyaXQpICU+JSAKICBiaW5kX3Jvd3MoYmVzdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9ub19zYW1lX25vX3plcm8pICU+JSAKICBiaW5kX3Jvd3MoYmVzdF9hc3ltX2Z1bGxfc2FtZV9zbG9wZV9zeW1fY3JpdF9zYW1lX25vX3plcm8pICU+JSAgCiAgYmluZF9yb3dzKGJlc3RfYXN5bV9mdWxsX3NhbWVfc2xvcGVfc3ltX2NyaXRfc2FtZV96ZXJvKSAKCgpyZWZzIDwtIGRhdF9hc3ltICU+JSBkaXN0aW5jdCh2ZXJ0aWNhbCwgcmVmZXJlbmNlcywgcmVmZXJlbmNlKQoKYXN5bV9hdmVyYWdlc19zX3ZzX2RfYmVzdCA8LSAgYXN5bV9hdmVyYWdlc19zX3ZzX2QgJT4lCiAgbGVmdF9qb2luKGJlc3RfYXN5bSkgJT4lIAogIGxlZnRfam9pbihyZWZzKQogIAphc3ltX2N1cnZlc19zX3ZzX2RfYmVzdCA8LSBhc3ltX2N1cnZlc19zX3ZzX2QgJT4lIAogIGxlZnRfam9pbihiZXN0X2FzeW0pICU+JSAKICBsZWZ0X2pvaW4ocmVmcykKCmFzeW1fcGFyX3NfdnNfZF9iZXN0IDwtIGFzeW1fcGFyX3NfdnNfZCAlPiUgCiAgbGVmdF9qb2luKGJlc3RfYXN5bSkgCgphc3ltX3Bhcl9zX3ZzX2RfYmVzdF9sb25nIDwtIGFzeW1fcGFyX3NfdnNfZF9sb25nICU+JSAKICBsZWZ0X2pvaW4oYmVzdF9hc3ltKSAKCgphc3ltX3Bhcl9zX3ZzX2RfYmVzdF9hYnMgPC0gYXN5bV9wYXJfc192c19kX2Jlc3RfbG9uZyAlPiUgCiAgc2VsZWN0KHN1YmplY3QsIHZlcnRpY2FsLCBwc2Vuc29yeSwgcGRlY2lzaW9uYWwsIGJlc3QpICU+JSAKICBnYXRoZXIocGFybiwgcGFyLCAtIHN1YmplY3QsIC0gdmVydGljYWwsIC1iZXN0KSAlPiUgCiAgbXV0YXRlKHBhcm4gPSBpZl9lbHNlKHBhcm4gPT0gInBzZW5zb3J5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNlbnNvcnlcbmJpYXMiLCAiRGVjaXNpb25hbFxuYmlhcyIpLAogICAgICAgICAgICAgICAgYWJzX3BhciA9IGFicyhwYXIpKQpgYGAKCiMjIyBTYXZlIGRhdGEKYGBge3J9CnNhdmUoYXN5bV9hdmVyYWdlc19zX3ZzX2RfYmVzdCwgZmlsZSA9ICJsb2dkYXRhL2FzeW1fYXZlcmFnZXNfc192c19kX2Jlc3QuUkRhdGEiKQpzYXZlKGFzeW1fY3VydmVzX3NfdnNfZF9iZXN0LCBmaWxlID0gImxvZ2RhdGEvYXN5bV9jdXJ2ZXNfc192c19kX2Jlc3QuUkRhdGEiKQpzYXZlKGFzeW1fcGFyX3NfdnNfZF9iZXN0LCBmaWxlID0gImxvZ2RhdGEvYXN5bV9wYXJfc192c19kX2Jlc3QuUkRhdGEiKQpzYXZlKGFzeW1fcGFyX3NfdnNfZF9iZXN0X2xvbmcsIGZpbGUgPSAibG9nZGF0YS9hc3ltX3Bhcl9zX3ZzX2RfYmVzdF9sb25nLlJEYXRhIikKc2F2ZShhc3ltX3Bhcl9zX3ZzX2RfYmVzdF9hYnMsIGZpbGUgPSAibG9nZGF0YS9hc3ltX3Bhcl9zX3ZzX2RfYmVzdF9hYnMuUkRhdGEiKQpgYGAKCgoKCg==